记一次Mongodb性能调优

原创文章,转载请注明来源并保留原文链接

1)关于索引

优化首先看查询是否有索引。

保证每次查询都可以走索引,可以用explain()查看,如果得到的cursor类型是`BasicCursor`,那么你要加索引了。

当一个字段属于多个索引的时候可以用`hint`来强制使用某一个索引。

谨慎使用`$in`和`$or`。

For queries that use the sort() method and use the $or operator, the query cannot use the indexes on the $or fields.

2)关于正则查找

如果Mongodb的正则查找使用 /^/ 匹配,索引可以生效,否则索引不生效,当数据量大的时候,性能非常糟糕。所以对于形如 /^/,/^a.*/,/^a.*$/,建索引吧。

对于非 /^/ 正则匹配,考虑使用全文检索吧,MongoDB 2.4 新引入了 Text Search

不过可惜的是,不支持中文,支持的语言可以查看这里,text-search-languages

所以在优化的过程中,我选择了solr来替代,solr最新的支持地理位置检索,可以很好的和MongoDB配合使用。

3)关于map/reduce

很麻烦,尽量不要使用。

4)关于aggregation

MongoDB2.2引入,基本可以满足大部分的聚合操作了,除了写起来很别扭。

Aggregation Framework Operators

今天用这个解决了一个问题,聚合还是放在数据库级别性能才足够优秀:

    def diary(opts = {})
      page       = opts[:page] || 1
      per_page   = opts[:per_page] || 20
      conditions = [{'$match' => {user_id: self.id, deleted_at: nil}}]
      conditions << {'$project' => {
        'year'  => {'$year'      => '$created_at'},
        'month' => {'$month'     => '$created_at'},
        'day'   => {'$dayOfYear' => '$created_at'},
        'date'  => '$created_at'
      }}
      conditions << {'$group' => {
        '_id' => {
          'year' => '$year', 'month' => '$month','day' => '$day'
        },
        'date' => { '$min' => '$date' },
        'food_stories' => { '$push' => '$_id' }
      }}
      conditions << {'$sort' => {'date' => -1}}
      conditions << {'$limit' => per_page}
      conditions << {'$skip'  => (page - 1)*per_page}
      Model.collection.aggregate(conditions)
    end

注意:如果你出现了,排序不正确,分页不正确,记得 $sort$limit$skip顺序有关,这几个操作要放在最后

One thought on “记一次Mongodb性能调优

  1. Pingback: 再看mongodb的分组group | Zires

Leave a Reply

Your email address will not be published. Required fields are marked *