mongo索引使用正则表达式注意事项

来源:互联网 发布:js给数组添加一个对象 编辑:程序博客网 时间:2024/06/06 06:42

正则表达式可以灵活地匹配查询条件,如果希望正则表达式能命中索引,就要注意了:

Mongodb能为前缀型的正则表达式命中索引,比如:需要查询Mail中user以z开头的:

/^z/

如果有user索引,这种查询很高效

但其他的即使有索引,也不会命中索引,比说:需要查询Mail中的user中含有z的:

/.*z.*/

/^.*z.*/

这种查询是不会命中到索引的,当数据量很大,速度很慢

总之,^后的条件必须明确,不能^.* ^[a-z]之类开头的

索引分析:

a)         索引命中:

假设索引为:{a:1,b:1,c:1,…,z:1}:

实际上是有了:{a:1},{a:1,b:1},{a:1,b:1,c:1}…等索引的。

但是使用{b:1}、{a:1,c:1}等索引的查询是会被优化的,只有使用索引前部的查询才能使用该索引。

Mongodb的查询优化器会重排查询项的顺序,以便命中索引,比如:查询{x:’a’,y:’b’}的时候,如果已有了{y:1,x:1}的索引,mongodb也会自己找到并命中的。

创建索引的缺点是每次插入、更新与删除时都会产生额外的开销,这是因为数据库不但需要执行这些操作,还是处理索引,因些,要尽量可能少创建索引。每个集合默认的最大索引个数为64个。

b)         查询时,不要使用$ne or $nin,这样不能命中索引

c)         使用explain

db.collection.find(query).explain();

返回的信息如下

{“cursor” : “BasicCursor”,

“indexBounds” : [ ],

“nscanned” : 57594,

“nscannedObjects” : 57594,

“nYields” : 2 ,

“n” : 3 ,

“millis” : 108,

“indexOnly” : false}

现实结果可以得知cursor的类型,DB扫描的数据数,返回的数据数,还有执行的毫秒数。

“cursor” : “BasicCursor”:

命中的索引,当为BasicCursor时表示没有命中任何索引

indexBounds: 所使用的索引,被设置为表示为索引扫描的关键边界。

nscanned – 扫描的数据条数。

nscannedObjects – 扫描对象的数。

nYields – 查询所产生的锁的个数。

isMultiKey- MongoDB中提供了可以自动索引数组对象的值

If true, a multikey index was used.

n- 返回文档的数量

millis- 数据库中执行查询的时间

indexOnly – 是否使用了covered index。

六、 强制索引:

如果发现mongodb用了非预期的索引,可以用hint强制用某个索引,如:

db.Mail.find({user:’zhaoxy1@szdep.com’,folderId:’inbox’}).hint(‘index1’)

多数情况下这种指定没有什么必要,mongodb会替你选择用哪个索引,初次查询时,查询优化器会同时尝试各种查询方案,最先完成的被确定使用,其他的则终止掉。查询方案也会记录下来,以备是后应对相同键的查询,查询优化器定期也重试其他的方案,以防因为添加新的数据后,之前的方案不再是最优的。

七、 为排序创建索引:

随着集合的增长,如果查询中有用到排序时,就要创建索引了。如果对没有索引的键用sort,mongodb需要将所有的数据提到内存中进行排序,这个是很影响性能的。

八、 索引优化:

这个是有人统计的不同数据类型所占的索引的大小:

另外,如果有关于日期的索引,我针对于String/Long/Date做了下测试:

可以看出,用Date类型所占的索引最小(Long/Date所占的大小差不多,1000w时也只相差3M左右),所以如果有需要日期索引的,需要将类型设置为Date或Long

九、 实例讲解:

以MA为例,场景为:

  1. 获取某个邮件夹的所有邮件列表
  2. 查看某个邮件夹中的已读邮件
  3. 查看某个邮件夹中的未读邮件
  4. 查看某个邮件夹中的重要邮件
  5. 查看某个邮件夹中的邮件来源

索引为:

{user:1,folderId:1,sendTime:-1,read:1,sourceSystem:1,importantFlag:1},{name:’folder_list_index’}

需要用到的查询条件组合(都需要以sendTime降序排列):

user:1,folderId:1,read:1,sourceSystem:1,importantFlag:1

user:1,folderId:1, read:1,sourceSystem:1

user:1,folderId:1,read:1

user,folderId, sourceSystem:1,importantFlag:1

user,folderId, sourceSystem:1

(红包部分必须hint,否则第一次速度会很快)

设计规则:

  1. 索引中的栏位,尽量用int类型,这样可减少索引的内存大小。

比如:sendTime的类型为Long,read、sourceSystem、importantFlag的类型为int

2.    索引的组合尽量包含常见的查询:

比如:获取邮件夹列表,查看邮件夹中的已读、未读邮件、重要邮件这几个查询很常用,设计索引时尽量包括这些查询

3.   有需要排序的栏位,要建索引,否则mongodb会在内存中排序。另外,排序索引尽量加在某个固定的大范围之后。

比如:获取邮件夹列表并按照sendTime降序排列,查询条件的大范围肯定要有user/folderId,此时,可将sendTime放在user/folderId之后,这样user/folderId对应的记录已经都以sendTime:-1的形式存放在索引库中(此时,用sort与不用sort的效果是相同的),sort时,也不用在内存中进行排序。如果有其他查询都在这个范围之内时,即使不能自动命中索引,也可以通过强制索引来提高查询的速度

4. 查询列表范围尽量小,数据量很多时,不加limit的查询会死人的。

原创粉丝点击