【MongoDb探究】08-索引

来源:互联网 发布:微信拼手气红包 算法 编辑:程序博客网 时间:2024/06/06 05:11
索引
在数据库中,索引明显提高查询速度,但是同时也会降低写入速度(因为插入数据的同时,也要创建索引),
所以我们通常权衡常用的查询字段,不必在太多列上建立索引。
我们的Mysql中有btree索引和hash索引,在mongodb中也支持这些索引。

(1)创建索引
1.在mongodb中,索引可以按字段升序/降序来创建,便于排序
2.默认是用btree来组织索引文件,2.4版本后也允许创建hash索引。

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


我们查询第99条数据:

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


其中,索引cursor如果是BasicCursor,就说明该查询没有使用索引。
没有使用索引的时候,查询就是一条一条的往后扫描,看一下nscannedObject的
数量,可以看出查询sn为99的用户理论上需要扫描1000行。

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

常用命令:
A.创建普通的单列索引:db.collection.ensureIndex({field:1/-1});
field就是我们需要添加索引的列明,1是正序排序,-1是倒叙排序。

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


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


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

其中,索引cursor如果是BtreeCursor sn 1,就说明该查询没有使用索引。
使用索引的时候,查询就是按照索引的目录去查询,看一下nscannedObject的
数量,可以看出查询sn为99的用户理论上只需要扫描1行。

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


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


D.创建多列索引:db.collection.ensureIndex({field:1/-1,field2:1/-1});
当我们需要使用多列来确定一条数据的时候,可能要创建多个索引,这个时候
给每一个列创建一个索引其实是不对的,那样的查询是依靠单个索引来的,并
没有起到综合查询的作用,想要实现多列联合索引插叙,就要创建多列索引。

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


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


E.创建子文档索引:db.collection.ensureIndex({field:subfield:1/-1});
我们新建一个shop文档,在其中添加两个商品,他们都有一个属性的子文档,
里面分别是“重量”和“产地”。


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


但是,当我们想查询产地为"taiwan"的商品,该如何查询呢?
我们查询子文档的时候,是使用子属性对象的引用来查询:


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


F.创建唯一索引:
db.collection.ensureIndex({field:subfield:1/-1}{unique:true});

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

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

默认创建的索引为_id。

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


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


G.创建稀疏索引:
稀疏索引的特点:如果针对field做索引,针对不含field列的文档,将不建立
索引。与之相对,普通索引,会把该文档的field列的值认为NULL,并建立索引。
适宜于:小部分文档含有某列时。

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

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


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

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

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


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



H.创建哈希索引(2.4新增)
哈希索引速度比普通索引快,但是不能对范围查询进行优化。
db.collection.ensureIndex({field:'hashed'});

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


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

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

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

I.重建索引
一个表经过很多此修改以后,会导致表的文件产生空洞,索引文件也如此。
可以通过索引的重建,来提高索引的效率,类似Mysql中的optimize table

db.collection.reIndex();


效果:减少索引文件碎片。
J.最后补充
二叉树查询和Hash的区别:


对于单个查询,hash查询效率高于tree查询,因为hash只需要计算一次。
但是对于区间查询(如查询1-100的数据),使用hash就比较慢了,因为hash存储
的数据是散列样式的,所以查询是跳着查的,而tree查询是顺序插叙,

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

转载请注明出处:http://blog.csdn.net/acmman/article/details/54574142

0 0
原创粉丝点击