0
点赞
收藏
分享

微信扫一扫

【MongoDb探究】08-索引


索引


在数据库中,索引明显提高查询速度,但是同时也会降低写入速度(因为插入数据的同时,也要创建索引),


所以我们通常权衡常用的查询字段,不必在太多列上建立索引。


我们的Mysql中有btree索引和hash索引,在mongodb中也支持这些索引。



(1)创建索引


1.在mongodb中,索引可以按字段升序/降序来创建,便于排序


2.默认是用btree来组织索引文件,2.4版本后也允许创建hash索引。



数据准备,我们先添加1000条数据:


【MongoDb探究】08-索引_btree



我们查询第99条数据:


【MongoDb探究】08-索引_btree_02


它的查询效率如何呢?我们看一下它的explain(查看查询计划):


【MongoDb探究】08-索引_spare_03



其中,索引cursor如果是BasicCursor,就说明该查询没有使用索引。


没有使用索引的时候,查询就是一条一条的往后扫描,看一下nscannedObject的


数量,可以看出查询sn为99的用户理论上需要扫描1000行。



为了提高我们的查询速度,可以通过创建索引来解决。



常用命令:


A.创建普通的单列索引:db.collection.ensureIndex({field:1/-1});


field就是我们需要添加索引的列明,1是正序排序,-1是倒叙排序。



我们为刚刚创建的数据添加索引,在sn列上添加:


【MongoDb探究】08-索引_mongodb_04



查看当前索引状态:db.collection.getIndexes();


【MongoDb探究】08-索引_ensureIndex_05



我们再次查询explain(查看查询计划):



其中,索引cursor如果是BtreeCursor sn 1,就说明该查询没有使用索引。


使用索引的时候,查询就是按照索引的目录去查询,看一下nscannedObject的


数量,可以看出查询sn为99的用户理论上只需要扫描1行。



B.删除单个索引:db.collection.dropIndex({field:1/-1});


【MongoDb探究】08-索引_btree_06



C.删除所有索引:db.collection.dropIndexes();


【MongoDb探究】08-索引_mongodb_07



D.创建多列索引:db.collection.ensureIndex({field:1/-1,field2:1/-1});


当我们需要使用多列来确定一条数据的时候,可能要创建多个索引,这个时候


给每一个列创建一个索引其实是不对的,那样的查询是依靠单个索引来的,并


没有起到综合查询的作用,想要实现多列联合索引插叙,就要创建多列索引。



我们给刚刚的student的sn属性和name属性都添加索引:


【MongoDb探究】08-索引_hash_08



多列索引的效率远远大于单列索引:


【MongoDb探究】08-索引_mongodb_09



E.创建子文档索引:db.collection.ensureIndex({field:subfield:1/-1});


我们新建一个shop文档,在其中添加两个商品,他们都有一个属性的子文档,


里面分别是“重量”和“产地”。


【MongoDb探究】08-索引_spare_10



当我们以商品名查询的时候很简单的就查询到了,比如查询商品名为"Nokia"的


商品:


【MongoDb探究】08-索引_spare_11



但是,当我们想查询产地为"taiwan"的商品,该如何查询呢?


我们查询子文档的时候,是使用子属性对象的引用来查询:


【MongoDb探究】08-索引_mongodb_12



那么给子属性添加索引的操作就类似如下:


【MongoDb探究】08-索引_hash_13



F.创建唯一索引:


db.collection.ensureIndex({field:subfield:1/-1}{unique:true});



唯一索引要求这个列上的值不能重复。



我们创建教师文档,其中email是不允许重复的


【MongoDb探究】08-索引_ensureIndex_14


默认创建的索引为_id。



然后我们为其email属性加索引,同时声明为唯一索引:


【MongoDb探究】08-索引_mongodb_15



我们创建两个email相同的数据,就会报错:


【MongoDb探究】08-索引_hash_16



G.创建稀疏索引:


稀疏索引的特点:如果针对field做索引,针对不含field列的文档,将不建立


索引。与之相对,普通索引,会把该文档的field列的值认为NULL,并建立索引。


适宜于:小部分文档含有某列时。



db.collection.ensureIndex({field:1/-1},{sparse:true});



我们去除之前的teacher文档的所有索引,然后添加一个空数据:


【MongoDb探究】08-索引_spare_17



我们给eamil创建一个普通索引,然后查询email为NULL的数据:


【MongoDb探究】08-索引_hash_18


发现普通索引,会把该文档的field列的值认为NULL,并建立索引



而稀疏索引的不同点就是,针对不含field列的文档,将不建立索引。


【MongoDb探究】08-索引_ensureIndex_19



我们再次查询email为NULL的数据就查询不出了,因为根本没有建立索引:


【MongoDb探究】08-索引_btree_20




H.创建哈希索引(2.4新增)


哈希索引速度比普通索引快,但是不能对范围查询进行优化。


db.collection.ensureIndex({field:'hashed'});



我们清除teacher的所有索引,并为email列创建hash索引:


【MongoDb探究】08-索引_mongodb_21



我们看一下它的explain(查看查询计划):


【MongoDb探究】08-索引_btree_22


说明查询的时候是按照哈希排列的key去查询的。



适宜于:随机性强的散列。



I.重建索引


一个表经过很多此修改以后,会导致表的文件产生空洞,索引文件也如此。


可以通过索引的重建,来提高索引的效率,类似Mysql中的optimize table



db.collection.reIndex();


【MongoDb探究】08-索引_ensureIndex_23



效果:减少索引文件碎片。


J.最后补充


二叉树查询和Hash的区别:

【MongoDb探究】08-索引_ensureIndex_24

【MongoDb探究】08-索引_spare_25

对于单个查询,hash查询效率高于tree查询,因为hash只需要计算一次。


但是对于区间查询(如查询1-100的数据),使用hash就比较慢了,因为hash存储


的数据是散列样式的,所以查询是跳着查的,而tree查询是顺序插叙,


可以快速锁定区域性数据。(机械硬盘的hash效率低于内存的hsah查询)


举报

相关推荐

0 条评论