关于mongodb:Mongoid到Mongo查询翻译

Mongoid to Mongo query translation

此问题已通过更简单的说明进行了更新。

对于我的数据,以下Mongo CLI查询需要208毫秒。此查询检索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()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
   "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(发布日期:-1,avg_rating:-1,标题:1).where(:avg_rating.gt => 1,:poster_large_thumb.exists => 1,1,:release_date.lte => start_date )。跳过(跳过* POSTERS_PER_ROW).limit(限制* POSTERS_PER_ROW)

当我迭代@videos时,每个对象都需要240毫秒以上的时间才能从DB中检索到,这是从某些调试输出中检索出来的。

1
2
3
4
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多花费几个数量级。


响应:

  • skip()。limit()查询在MongoDB方面会越来越慢。跳过文档时,请参阅此处的更多信息https://stackoverflow.com/a/7228190/534150

  • 多个相同的查询在我看来是N 1类型的问题。这意味着可能在您的视图中的某个地方,您有一个循环调用一个延迟加载的属性,因此它会反复发送查询。这些问题通常很难发现,但是要跟踪它们,您需要进行端到端跟踪,因为您可以访问源代码,所以您可能是唯一可以做到这一点的跟踪器。

  • 对我来说,Mongoid一侧看起来很正确。


  • 感谢您的想法,我认为@Arthur提供了重要提示。没有人可以回答,因为看起来问题出在另一段代码中,即我访问标准的方式。

    给出以下查询,该查询将产生一个条件:

    1
    @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)

    在几个嵌套块中,我使用如下代码行来获取值:

    1
    video_full = @videos[((row_index)*POSTERS_PER_ROW)+column_index]

    此随机访问符号似乎是问题所在。似乎对每个单个对象执行完整的Moped查询,因此POSTERS_PER_ROW * num_rows次。

    如果我使用以下代码在循环之前抓取所有视频:

    1
    2
    3
    @videos.each do |video|
        videos_full.push video
    end

    然后从数组中获取值,而不是像这样的条件:

    1
    video_full = videos_full[((row_index)*POSTERS_PER_ROW)+column_index]

    我只收到一个248ms的Moped查询,所有的对象都通过该查询来检索。这是一个巨大的速度。查询时间从num_rows * POSTERS_PER_ROW * 248ms变为248ms

    这对我来说是一个重要的教训,因此,如果有人可以指向描述此效果的文档以及要遵循的规则,我将不胜感激。