通过更简单的解释更新此问题。
对于我的数据,以下Mongo CLI查询需要208ms。此查询检索18个请求对象的所有数据。
db.videos.find({avg_rating:{$ gt:1},poster_large_thumb:{$ exists:true},release_date:{$ lte:ISODate(“2000-12-31”)}})。sort( {release_date:-1,avg_rating:-1,title:1})。skip(30).limit(18).pretty()。explain()
{
"cursor" : "BasicCursor",
"nscanned" : 76112,
"nscannedObjects" : 76112,
"n" : 48,
"scanAndOrder" : true,
"millis" : 208,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
然而,当我进行查询时,使用Mongoid会创建一个没有实际数据的条件对象。我将此标准传递给迭代它以创建JSON数据结构的方法。由于需要数据,因此必须从数据库中检索每个对象。以下是返回查询的条件:
@videos = Video.order_by(release_date:-1,avg_rating:-1,title:1).where(:avg_rating.gt => 1,:poster_large_thumb.exists => 1,:release_date.lte = > start_date).skip(skip * POSTERS_PER_ROW).limit(limit * POSTERS_PER_ROW)
当我迭代@videos时,每个对象需要240多秒来从数据库中检索,这来自一些调试输出。
Getting one object:
2013-12-18 00:43:52 UTC
2013-12-18 00:43:52 UTC
0.24489331245422363
假设如果我获得了Video.order_by(...)查询中的所有数据,那么总共需要208ms,我如何强制它在一个查询中执行检索而不是单独获取每个对象?
这里的一些东西导致整个检索比Mongo CLI多了几个数量级。
答案 0 :(得分:1)
对策:
skip()。limit()查询在MongoDB端往往变得越来越慢。当跳过文档时,有关详细信息,请参阅此处https://stackoverflow.com/a/7228190/534150
多个相同的查询在我看来是一个N + 1类型的问题。这意味着,在您的视图中,您可能有一个循环调用延迟加载的属性,因此它会一遍又一遍地发送查询。这些问题通常很难找到,但要跟踪它们,您需要拥有端到端的跟踪,您可能是唯一能够做到这一点的跟踪,因为您可以访问源代码。
< / LI>Mongoid方面对我来说是正确的。
答案 1 :(得分:0)
感谢这些想法,我认为@Arthur给出了重要的暗示。没有人能够回答,因为看起来问题出现在另一个代码中 - 我如何访问标准。
给出以下查询,它产生一个标准:
@videos = Video.order_by(release_date: 1, avg_rating: 1, title: -1).where(:release_date.ne => 0,:avg_rating.gt => 1, :poster_large_thumb.exists => 1, :release_date.gt => start_date).skip(skip*POSTERS_PER_ROW).limit(limit*POSTERS_PER_ROW).only(:_id, :poster_large_thumb, :title)
在一个嵌套的块中,我用一行代码来抓取值:
video_full = @videos[((row_index)*POSTERS_PER_ROW)+column_index]
这种随机访问符号似乎是个问题。它似乎为每个单独的对象执行完整的Moped查询,因此POSTERS_PER_ROW * num_rows次。
如果我使用这段代码抓住循环之前的所有视频:
@videos.each do |video|
videos_full.push video
end
然后从数组中获取值而不是像这样的条件:
video_full = videos_full[((row_index)*POSTERS_PER_ROW)+column_index]
我只获得一个248毫秒的Moped查询,所有对象都使用该查询检索。这是一个巨大的加速。查询时间从num_rows * POSTERS_PER_ROW * 248ms变为仅248ms
这对我来说是一个很大的教训,所以如果有人可以指出描述这种效果的文档以及要遵循的规则,我一定会很感激。