今天在开发公司评论系统的新需求时,碰到一个关于mongo sort排序的问题
条件:
1. 评论表comment中包含两个字段 ctime(添加时间),like(点赞的人数)
2. comment表中的数据为1000万+
3. 无索引(没有给ctime,like添加任何索引)
4. php查询mongo的超时时间设置的是1s
查询:
db.comment.find().skip(0).limit(*).sort({'ctime':-1})
//按照ctime排序
没有报错,查询时间不到1s
db.comment.find().skip(0).limit(*).sort({'like':-1})
//按照like排序
报错:超时,发现查询时间为2s到3s
此图为无索引
为什么会出现这个问题呢?当时很困惑,ctime与like的级别是一样的,都没有加索引且都是int型数据,为什么一个查询不到1s,一个要2s+?
突然一道金光射入我的脑子我一下就明白了!!
因为如果按ctime排序的话,这个数组就为有序数组,如果按like排序的话,这个数组就为无序数组。无序数组排序比有序排序的时间复杂度要大。
note:一条记录在添加时ctime是递增的,而like是离散的数字
问题现在搞清楚了,现在怎么解决呢?
怎样才能让db.comment.find().skip(0).limit(*).sort({'like':-1})的查询效率变高?
在不影响业务的情况下,我选择了给like添加索引,但如何添加索引是个问题了。一般我们都知道不给选择性低的字段添加索引,因为这个不能提高效率。那该如何做呢?
答案:就是添加组合索引
策略是创建组合索引包括这个低选择性的字段。(即:选择性高的字段+选择性低的字段)
方案一
db.comment.ensureIndex({'ctime':1,'like':-1})
//添加组合索引
db.comment.find().skip(0).limit(*).sort({'like':-1})
此图索引为{'ctime':1,'like':-1}
从图上看出,还是索引没有起作用,这是因为组合索引中,用右边的字段索引,索引不起作用。
方案二
db.comment.ensureIndex({'like':-1,'ctime':1})
//添加组合索引
db.comment.find().skip(0).limit(*).sort({'like':-1})
此图索引为{'like':-1,'ctime':1}
发现效率明显提高了很多
了解组合索引的优化原理请读:10gen工程师谈MongoDB组合索引的优化
关于mysql数据库索引 http://www.uml.org.cn/sjjm/201107145.asp
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。