第26章:MongoDB-索引

时间:2021-04-14 19:57:07
①索引
索引本质上是树,最小的值在最左边的叶子上,最大的值在最右边的叶子上,使用索引可以提高查询速度(而不用全表扫描),也可以预防脏数据的插入(如唯一索引)。

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。

这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

②原理
对某个键按照升续或降续创建索引,查询时首先根据查询条件查找到对应 的索引条目找到,然后找对索引条目对应的文档指针(文档在磁盘上的存储位置),根据文档指针再去磁盘中找到相应的文档,整个过程不需要扫描全表,速度比较快。
 
["along"] —-> 0x0c965148(文档指针) 
…… 
["zhangsan"] —-> 0x0c965148(文档指针)
③类型

唯一索引unique:保证数据的唯一不重复

稀疏索引sparse

TTL 索引:设置文档的缓存时间,时间到了会自动删除掉

全文索引:便于大文本查询(如概要、文章等长文本)

复合索引:用于提高查询速度

二维平面索引:便于2d平面查询

地理空间索引:便于地理查询

④索引的管理
// 创建索引ensureIndex(keys, options);

索引的选项

name:"", 自定义索引的名称,不配置系统会有默认的索引名

--db.students.ensureIndex({"name":"张三"},{"name":"myindex"});

background: true, 默认是前台模式, 创建索引是一件即费事又耗费资源的事情,创建索引是在前台模式或者后台模式下创建,在前台模式下创建非常快,但是当有读写请求时会堵塞,在后台模式下当有读写请求时并不堵塞,但是创建索引就会暂时暂停,后台模式要比前台模式慢的多

unique: true,唯一索引

dropDups: true,是否强制删除其他重复的文档,默认不删除,当索引键值重复时创建失败

sparse: true, 稀疏索引: 只对包含了该索引键的文档生成索引条目,不包含该键就跳过不生成索引键,可以和唯一索引配合使用,也可以单独使用

范例:

db.students.ensureIndex({"userid":"1"});

// 查询索引getIndexes(filter);
范例:
db.students.getIndexes();
// 查看查询语句解释
explain();

explain的字段说明:

1:cursor:本次查询使用的索引

2:isMultiKey:是否使用了多键索引

3:n:返回的文档数量

4:nscannedObjects:按照索引指针去磁盘查找实际文档的次数

5:nscanned:如果使用索引,就是查找过的索引条目数量;如果全表扫描,就是查找过的文档数量

6:scanAndOrder:是否在内存中对结果集排序

7:indexOnly:是否只是用索引就能完成本次查询

8:nYields:为了让写入请求能顺利执行,本次查询暂停的次数

9:millis:本次查询所耗费的时间,单位是毫秒

10:indexBounds:描述索引的使用情况,给出了索引的遍历范围

范例:

db.students.find({"name":"张三"}).explain();

// 删除索引dropIndex("IndexName");

范例:删除一个索引

db.students.dropIndex({"age"-1});

范例:删除全部索引--所谓的删除全部索引指的就是非"_id"的索引,所有的自定义索引。

db.students.dropIndexes();

⑤使用效率

索引键基数越大,效率越高。

基数:就是某个字段不同值的个数(相当于SQL中的 count(distinct key)),如性别就2个,如用户名和邮箱几乎都不同,所以不同值的个数就很多,基数越大,使用索引快速筛选掉不满足条件的文档越快,基数越小就不能快速筛选满足条件的文档

一些特殊的操作符不能使用索引,如 $where、$exists

一般取反的操作符索引利用率都比较低,如$not、$nin、$ne

如果能使用$in操作符尽量不要使用$or操作符,因为or: 是执行两次查询操作,然后将结果合并起来,类似于union all,能使用in(单次查询)就不要使用or操作符

如果查询要在内存中排序的话,结果集不能超过32M

MongoDB限制每个集合上最多只能有64个索引,建议在一个特定的集合上,不要设置多个索引。

⑥什么时候创建索引
当需要对查询优化,或者经常使用某种查询的时候可以创建索引来提高查询效率
⑦应该选哪些字段创建索引
一般应该在基数比较高的键上建立索引,或者至少把基数较高的键放在复合索引的前面位置