Mongodb 被忽略的 数据类型 索引种类 与限制与如何导向开发者 (2 索引种类与 ESR)...

8764af3ff85bfdf1958f65112e485119.png

接上期MONGODB 中的数据的快速查找是通过索引来进行的,这里来先把一些INDEX 中MONGODB 在索引中的词汇来捋一捋, 如voverd query 覆盖查询, IXCSAN索引扫描  COLLSCAN 全collection 扫描, Query shape  , index prefix 前缀索引 , selectivity 过滤性。

关于INDEX 的种类,MONGODB 主要分为以下种类的INDEX 

单建索引

组合索引

多值索引  多键索引

地理位置索引

全文索引

TTL 索引

部分索引

HASH 索引

跳跃索引 稀疏索引

在一个MONGODB 的语句执行中,也有类似与传统数据库的执行方式,首先语句与执行计划中的缓存匹配,如果发现执行过,则可能直接走原有的计划,如不可以,会生成新的候选计划,在评估候选计划,通过对不同的优化方式进行测试,最终得出最优的计划, 创建计划缓存。最终通过执行器将计划进行执行,与其他的数据库类型,可以强制MONGODB 使用预定的索引。

1  ESR 原则

对于MONGODB 重要的第一个索引的关联项和知识点是MONGODB 的组合查询中的配对的索引的 ESR 原则, Equal  , sort , range  , 对应不同的查询可能会更简化为 ES  , ER。 

这里的意思简单用一句话来描述, 查询中的索引与查询需要匹配一个 等值计算,排序, 范围 这样一个顺序。

下面通过一个查询和三个索引来说明问题

1772545d347845bf963f42163fe48b11.png

在一个collection 建立三个索引,其中不同的是索引中字段的顺序

db.zips.createIndex(

                  {"city": 1,"_id":1,"pop":1},

                  {background:true} )

db.zips.createIndex(

                  {"_id":1,"city": 1,"pop":1},

                  {background:true} )

db.zips.createIndex(

                  {"pop":1,"_id":1,"city": 1},

                  {background:true} )                  

db.zips.find({city:"AGAWAM",pop:{$gt:15337}}).sort("_id": 1).explain("executionStats")

a14567f670293b904972e70bb63e5e88.png

查询中可以看到三个索引,在查询中,使用了根据上面的ESR原则建立的索引,而并没有用其他的索引。

db.zips.dropIndex("city_1__id_1_pop_1")

在我们删除最优选后,在此查询 可以看到查询的方式变为了 SR 模式

63879a66306ceed87174f164ab91c39b.png

db.zips.createIndex(

                  {"city": 1,"_id":1,"pop":1},

                  {background:true} )

db.zips.createIndex(

                  {"_id":1,"city": 1,"pop":1},

                  {background:true} )

db.zips.createIndex(

                  {"pop":1,"_id":1,"city": 1},

                  {background:true} )                  

db.zips.find({city:"AGAWAM",pop:{$gt:15337}}).sort("_id": 1).explain("executionStats")

db.zips.dropIndex("city_1__id_1_pop_1")

db.zips.dropIndex("pop_1__id_1_city_1")

依次对索引进行删除可以看到如何ESR 原理的查询和索引性能是最优的,其次是SR。 每种不同的索引会导致  docsExamined 评估数的不同

0b18eb937fda525b74c6545aaf357442.png

681c1196f9fcef9c242cc185bac48836.png

9260368754d3a7c3c3e0d8abb9153e4c.png

这个例子的优化点用一句话表达就是,缩小范围,顺序定位,缩小范围,减少最后的排序组合,这样在多个字段的索引中,定位是最快的,避免搜集过多的document ,在进行filiter.

2  全文索引

MONGODB 在2.4就已经有了全文索引,全文索引的没有在MONGODB 中大量使用的原因是数据量大了后,性能的问题。 在MONGODB 4.2后的Altas的全文索引采用了新的方法,有兴趣的可以查询相关的内容。这里还是说老的mongodb community 的中的FULL TEXT . MONGODB 的全文索引,1个collection中只能拥有一个全文索引。

ce972ac28d798d1daf88ced26ff2ed16.png

 全文索引需要注意的是一个查询中只能有一个全文索引,并且不能在全文索引中使用HINT,同时也不能使用$natural 进行排序,同时如果有地理数据查询时不能预地理索引一起进行查询。对于中午的全文索引查询也要注意一些特殊的情况和设置。

3  跳跃索引 或 稀疏索引

Mongodb 属于NOSQL 数据库库,其中最主要的特点是每个document (ROWS) 都可能是不一样的,而索引本身的特性就是对于操作的数据要求每行都存在,这里就产生了矛盾。

稀疏索引就是解决这个问题的,

db.places.createIndex({"name": 1}, {sparse: true ,background:true})

c0d8278ee9ae31cba698d57f276efaa9.png

通过在  create index 时添加 sparse 稀疏索引降低索引在无KEY VALUE 的情况下不会对这个document 的不存在的KEY 进行 NULL 的索引的建立。

4  部分索引

部分索引并不是类似MYSQL 的前缀索引,而是根据条件来建立索引,可以这样理解一部分数据在collection中建立索引,一部分数据在collection不建立索引。下面是一个例子,我们仅仅对pop 中数据库大于1000的数据进行索引的操作。那么这个索引的好处也很明显,在符合你的条件的基础上的查询都可以走索引,索引的容量小,效率高。

db.zips_purea.createIndex({pop:1},{partialFilterExpression:{pop:{$gt:1000}}})

db.zips_purea.find({pop:{$gt:1200}}).explain()

5ce0554121f5a527a477441c4bdf991d.png

条件变化了,已经不再我们的条件之内了,可以看见查询就不再使用索引了,为什么,因为索引没有建立,一部分数据并没有

4cac55a2e7146a3ecde3fe306104f49e.png

5  TTL 索引

MONGODB 的TTL 索引或者叫 expired time  INDEX , TTL 索引主要的公用就是数据的过期清理,REDIS 本身是可以对键值进行设置,通过键值的过期时间来在规定的时间将键值清理的,MONGODB 为什么也会有这样的一个功能,个人从这几年的MONGODB 的使用的过程中,深深的体会这个功能的重要性,MONGODB 本身承载的数据,不同应用的报文承接,日志记录的功能,用户信息的查询等等,这些场景的应用中都有一个不可回避的问题,就是数据的时效性。数据在这些场景中都是有时效性的,过期后数据就不在被使用,一般的数据库都不会具有自动清理数据的功能,MOGNODB 通过TTL 索引设置时间的方式,将数据到期后,根据数据库本身性能的要求,在满足数据库空闲时进行过期数据的清理的工作。

4973f6b189b37fe364eb4b9eff159aab.png

我们打开一个COLLECTION,并且其中有一条记录是包含时间的,这里TTL索引加你了以data2 为字段,超过300秒就开始清理数据的TTL 索引。

db.data.createIndex({"data2":1},{expireAfterSeconds:300})

c504546f3a3f5997161f9d26da40a7d9.png

在索引建立后,300秒后,我们查看到底数据有没有被清理出去, 再次查询,的确数据已经被删除了。

但,但就怕说但,很多同学反馈说,建立了索引不能删除数据那么可以看看是否有以下的问题

1  字段的类型,字段的类型必须是ISODATE 类型,文本格式的数据是无法被识别的。

2  时间在数据组中,如果时间在数组中包含多个时间值,以时间最早的作为清理的基准(但是在不建议这样做,还是规规矩矩的建立一个时间KEY VALUE 很难吗)

3  文档中并不包含这个KEY VALUE ,则这个文档永远不会被删除

4  数据库处于繁忙,未达到可以清理的阀值的情况下,数据库会进行轮训,达到轮训时间,但系统性能不达标的情况下,不会清理数据,系统默认60秒轮训一次。

5  从库的数据操作,并不通过TTL索引,相关操作是通过主库OP LOG 推送的。

6   TTL 索引本身具有普通INDEX的功能,一箭双雕。

e32f0dbed1725c1457a03ba19a57501c.png

6  HASH 索引

HASH 索引本身的功能是在MONGODB 分片的情况下进行工作的,也就是并不是普通的复制集,或单体的MONGODB 有这个需求,或功能。 建立这个功能也是通过针对 _id 主键加索引的方式。

b42742c7e4f91452eafa0940a7b82287.png

在MONGODB 4.4 hash index 本身已经支持了compound hash index 这里由于本身的特性以及使用场景,就不在深入了。这里多说一句关于MOGNODB数据分片的问题,MONGODB 分片 HASH  RANGE 这两种方式都会针对不同的业务场景,也都有各自的缺陷,用好了性能提升,用不好,性能和单机相比会有很大的衰减,所以不要一提分片就认为是解决问题的第一个方法。

7  地理索引  2d indexes  

地理索引面向的是MONGODB 的地理数据查询方式,通过地理索引可以快速的处理地理数据信息。

具体的使用方式,需要地理查询的特殊方式,这里不再详述,需要了解详情的的同学可以打开下方的连接。

Mongodb GeoJSON 地理数据处理 其实我也很厉害

https://mp.weixin.qq.com/s?__biz=Mzg4NDA0NTEwNA==&mid=2247494621&idx=1&sn=5ee53df3b1cae7835d529e2efda61347&chksm=cfbc8f82f8cb069490a31fe57cca6d4397dab23686ee1b755ddc5fb08d770ce5e29333765889&token=959999716&lang=zh_CN#rd

小结:

mongodb 本身的索引种类与传统数据库部分相同,部分不同,不同的部分以自身的MONGODB数据的类型,数据的存储方式,以及业务场景有关。所以用好MONGODB 的第一个条件,就是识别业务场景,那些业务场景适合,剩下的才是MONGODB 的数据存储设计(schema )与 索引的性能支持。

68bd424c7e155cd822dc6dedbe7b8244.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值