Ruby eager查询导致加载问题

5jvtdoz2  于 2022-12-03  发布在  Ruby
关注(0)|答案(1)|浏览(86)

为了解释我所面临的问题,让我举一个来自RubySequel文档的例子。

Album.eager(:artists, :genre).all

如果数据相对较少,这将是好的。
如果数据量很大,这个查询将触发数以千计的artist_id。如果数据量以百万计,则将收集一百万个artist_id。是否有办法获取相同的输出,但使用不同的优化查询?

h5qlskok

h5qlskok1#

只是不要急于加载大数据集,也许?:)
(TL;DR:这不是一个答案,而是一个罗嗦的方式说“没有一个简单的答案”:))
简单问题的简单解决方案。默认的(幼稚的)急切加载策略有效地解决了相当小的关系的N+1问题,但如果你试图急切加载巨大的关系,你可能会(也会)自杀。
例如,如果您只获取1000个带有id的相册,(1到1000)、那么您的ORM将触发额外的急切加载查询,以查找in列表中可能包含1000个id的select * from <whatever> where album_id in (1,2,3,...,1000)这样的艺术家和流派。where ... in查询的性能可能不是最佳的,即使是在现代数据库中,其查询计划器像爱因斯坦一样聪明。在一定的数据规模下,即使是如此小的一批数据,这也会变得非常慢。如果您尝试立即加载 * Just everything*(如您的示例中所示)-几乎不适用于任何实际数据使用(除了最小的用例)。
所以,
1.一般情况下,最好避免加载“全部”,而是批量加载数据;

  1. EXPLAIN是您最好的朋友-始终分析您的ORM触发的查询。即使是经过实战测试的生产级ORM也可能(并且将)不时产生次优查询;
    1.后者对于大型数据集尤其如此--在一定的规模下,您将别无选择,只能从优秀的ORM API迁移到较低级别的定制SQL查询(至少对于瓶颈);
    1.在一定的规模,甚至自定义SQL将不再有帮助-该规模的问题需要在另一个层面上解决(数据重塑,缓存,分片,CQRS等等...)

相关问题