快速掌握mongoDB(三)——mongoDB的索引详解
<h2 class="para">1 mongoDB索引的管理</h2><div class="para"> 本节介绍mongoDB中的索引,熟悉mysql/sqlserver等关系型数据库的小伙伴应该都知道索引对优化数据查询的重要性。我们先简单了解一下索引:索引的本质就是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据(数据row或者document)的物理地址,索引可以大大加快查询的速度,这是因为使用索引后可以不再扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址(多数为B-tree查找),然后通过地址来访问相应的数据。</div>
<div class="para"> 索引可以加快数据检索、排序、分组的速度,减少磁盘I/O,但是索引也不是越多越好,因为索引本身也是数据表,需要占用存储空间,同时索引需要数据库进行维护,当我们对索引列的值进行增改删操作时,数据库需要更新索引表,这会增加数据库的压力。</div>
<div>我们要根据实际情况来判断哪些列适合添加索引,哪些列不适合添加索引,一般遵循的规律如下:</div>
<div> 主/外键列,主键用于强制该列的唯一性和组织表中数据的排列结构;外键可以加快连接的速度;</div>
<div> 经常用于比较的类(大于小于等于等),因为索引已经排序,值就是大于/小于的分界点;</div>
<div> 经常进行范围搜索,因为索引已经排序,其指定的范围是连续的;</div>
<div> 经常进行排序的列,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;</div>
<div> 经常进行分组的列,因为索引已经排序,同一个值的所有数据地址会聚集在一块,很方便分组。</div>
<div>我们看一下mongoDB的索引使用,首先准备数据:</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">db.userinfos.insertMany([
{_id:</span><span style="color: rgba(128, 0, 128, 1)">1</span>, name: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span>, age: <span style="color: rgba(128, 0, 128, 1)">23</span>,level:<span style="color: rgba(128, 0, 128, 1)">10</span>, ename: { firstname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">san</span><span style="color: rgba(128, 0, 0, 1)">"</span>, lastname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">zhang</span><span style="color: rgba(128, 0, 0, 1)">"</span>}, roles: [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">vip</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gen</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ]},
{_id:</span><span style="color: rgba(128, 0, 128, 1)">2</span>, name: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">李四</span><span style="color: rgba(128, 0, 0, 1)">"</span>, age: <span style="color: rgba(128, 0, 128, 1)">24</span>,level:<span style="color: rgba(128, 0, 128, 1)">20</span>, ename: { firstname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">si</span><span style="color: rgba(128, 0, 0, 1)">"</span>, lastname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">li</span><span style="color: rgba(128, 0, 0, 1)">"</span>}, roles:[ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">vip</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ]},
{_id:</span><span style="color: rgba(128, 0, 128, 1)">3</span>, name: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">王五</span><span style="color: rgba(128, 0, 0, 1)">"</span>, age: <span style="color: rgba(128, 0, 128, 1)">25</span>,level:<span style="color: rgba(128, 0, 128, 1)">30</span>, ename: { firstname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">wu</span><span style="color: rgba(128, 0, 0, 1)">"</span>, lastname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">wang</span><span style="color: rgba(128, 0, 0, 1)">"</span>}, roles: [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gen</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">vip</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ]},
{_id:</span><span style="color: rgba(128, 0, 128, 1)">4</span>, name: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">赵六</span><span style="color: rgba(128, 0, 0, 1)">"</span>, age: <span style="color: rgba(128, 0, 128, 1)">26</span>,level:<span style="color: rgba(128, 0, 128, 1)">40</span>, ename: { firstname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">liu</span><span style="color: rgba(128, 0, 0, 1)">"</span>, lastname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">zhao</span><span style="color: rgba(128, 0, 0, 1)">"</span>}, roles: [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gen</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">] },
{_id:</span><span style="color: rgba(128, 0, 128, 1)">5</span>, name: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">田七</span><span style="color: rgba(128, 0, 0, 1)">"</span>, age: <span style="color: rgba(128, 0, 128, 1)">27</span>, ename: { firstname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">qi</span><span style="color: rgba(128, 0, 0, 1)">"</span>, lastname: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tian</span><span style="color: rgba(128, 0, 0, 1)">"</span>}, address:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">北京</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> },
{_id:</span><span style="color: rgba(128, 0, 128, 1)">6</span>, name: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">周八</span><span style="color: rgba(128, 0, 0, 1)">"</span>, age: <span style="color: rgba(128, 0, 128, 1)">28</span>,roles:[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gen</span><span style="color: rgba(128, 0, 0, 1)">"</span>], address:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">上海</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> }
]);</span></pre>
</div>
<p> 索引的增删改查还是十分简单的,我们看一下索引管理的几个方法:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建索引,值1表示正序排序,-1表示倒序排序</span><span style="color: rgba(0, 0, 0, 1)">
db.userinfos.createIndex({age:</span>-<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查看userinfos中的所有索引</span>
<span style="color: rgba(0, 0, 0, 1)">db.userinfos.getIndexes()
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除特定一个索引</span>
db.userinfos.dropIndex({name:<span style="color: rgba(128, 0, 128, 1)">1</span>,age:-<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除所有的索引(主键索引_id不会被删除)</span>
<span style="color: rgba(0, 0, 0, 1)">db.userinfos.dropIndexes()
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果我们要修改一个索引的话,可以先删除索引然后在重新添加。 </span></pre>
</div>
<h2>2 mongoDB中常用的索引类型</h2>
<h3>1 单键索引</h3>
<p> 单键索引(Single Field Indexes)顾名思义就是单个字段作为索引列,mongoDB的所有collection默认都有一个单键索引_id,我们也可以对一些经常作为过滤条件的字段设置索引,如给age字段添加一个索引,语法十分简单:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给age字段添加升序索引</span>
db.userinfos.createIndex({age:<span style="color: rgba(128, 0, 128, 1)">1</span>})</pre>
</div>
<p> 其中{age:1}中的1表示升序,如果想设置倒序索引的话使用 <span class="cnblogs_code">db.userinfos.createIndex({age:-<span style="color: rgba(128, 0, 128, 1)">1</span>})</span> 即可。我们通过explain()方法查看查询计划,如下图,看到查询age=23的document时使用了索引,如果没有使用索引的话stage=COLLSCAN。</p>
<p><img style="border: 2px solid rgba(0, 0, 255, 1)" src="https://img2018.cnblogs.com/blog/1007918/201906/1007918-20190616162439895-28686184.png" alt=""></p>
<p> 因为document的存储是bson格式的,我们也可以给内置对象的字段添加索引,或者将整个内置对象作为一个索引,语法如下:</p>
<div class="cnblogs_code">
<pre><strong><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1.内嵌对象的某一字段作为索引
</span></strong><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在ename.firstname字段上添加索引</span>
db.userinfos.createIndex({<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ename.firstname</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用ename.firstname字段的索引查询</span>
db.userinfos.find({<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ename.firstname</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">san</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">})
</span><strong><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2.整个内嵌对象作为索引
</span></strong><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给整个ename字段添加索引</span>
<span style="color: rgba(0, 0, 0, 1)">db.userinfos.dropIndexes()
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用ename字段的索引查询</span>
db.userinfos.createIndex({<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ename</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 128, 1)">1</span>})</pre>
</div>
<h3>2 复合索引</h3>
<p> 复合索引(Compound Indexes)指一个索引包含多个字段,用法和单键索引基本一致。使用复合索引时要注意字段的顺序,如下添加一个name和age的复合索引,name正序,age倒序,document首先按照name正序排序,然后name相同的document按age进行倒序排序。mongoDB中一个复合索引最多可以包含32个字段。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加复合索引,name正序,age倒序</span>
db.userinfos.createIndex({<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 128, 1)">1</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span>:-<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">过滤条件为name,或包含name的查询会使用索引(索引的第一个字段)</span>
db.userinfos.find({name:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">}).explain()
db.userinfos.find({name:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span>,level:<span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">}).explain()
db.userinfos.find({name:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span>,age:<span style="color: rgba(128, 0, 128, 1)">23</span><span style="color: rgba(0, 0, 0, 1)">}).explain()
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询条件为age时,不会使用上边创建的索引,而是使用的全表扫描</span>
db.userinfos.find({age:<span style="color: rgba(128, 0, 128, 1)">23</span>}).explain()</pre>
</div>
<p> 执行查询时查询计划如下:</p>
<p><img style="border: 2px solid rgba(0, 0, 255, 1)" src="https://img2018.cnblogs.com/blog/1007918/201906/1007918-20190616165236071-2077681014.png" alt=""></p>
<h3>3 多键索引</h3>
<p> 多键索引(mutiKey Indexes)是建在数组上的索引,在mongoDB的document中,有些字段的值为数组,多键索引就是为了提高查询这些数组的效率。看一个栗子:准备测试数据,classes集合中添加两个班级,每个班级都有一个students数组,如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">db.classes.insertMany([
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">classname</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">class1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">students</span><span style="color: rgba(128, 0, 0, 1)">"</span>:[{name:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">jack</span><span style="color: rgba(128, 0, 0, 1)">'</span>,age:<span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">},
{name:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">tom</span><span style="color: rgba(128, 0, 0, 1)">'</span>,age:<span style="color: rgba(128, 0, 128, 1)">22</span><span style="color: rgba(0, 0, 0, 1)">},
{name:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">lilei</span><span style="color: rgba(128, 0, 0, 1)">'</span>,age:<span style="color: rgba(128, 0, 128, 1)">25</span><span style="color: rgba(0, 0, 0, 1)">}]
},
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">classname</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">class2</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">students</span><span style="color: rgba(128, 0, 0, 1)">"</span>:[{name:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">lucy</span><span style="color: rgba(128, 0, 0, 1)">'</span>,age:<span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">},
{name:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">jim</span><span style="color: rgba(128, 0, 0, 1)">'</span>,age:<span style="color: rgba(128, 0, 128, 1)">23</span><span style="color: rgba(0, 0, 0, 1)">},
{name:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">jarry</span><span style="color: rgba(128, 0, 0, 1)">'</span>,age:<span style="color: rgba(128, 0, 128, 1)">26</span><span style="color: rgba(0, 0, 0, 1)">}]
}]
)</span></pre>
</div>
<p> 为了提高查询students的效率,我们使用 <span class="cnblogs_code"> db.classes.createIndex({<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">students.age</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 128, 1)">1</span>})</span> 给students的age字段添加索引,然后使用索引,如下图:</p>
<p><img style="border: 2px solid rgba(0, 0, 255, 1)" src="https://img2018.cnblogs.com/blog/1007918/201906/1007918-20190616181241314-1941755772.png" alt=""></p>
<h3> 4 哈希索引</h3>
<p> 哈希索引(hashed Indexes)就是将field的值进行hash计算后作为索引,其强大之处在于实现O(1)查找,当然用哈希索引最主要的功能也就是实现定值查找,对于经常需要排序或查询范围查询的集合不要使用哈希索引。</p>
<p><img style="border: 2px solid rgba(0, 0, 255, 1)" src="https://img2018.cnblogs.com/blog/1007918/201906/1007918-20190616184350043-240369758.png" alt=""></p>
<h2>3 mongoDB中常用的索引属性</h2>
<h3>1 唯一索引</h3>
<p> 唯一索引(unique indexes)用于为collection添加唯一约束,即强制要求collection中的索引字段没有重复值。添加唯一索引的语法:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在userinfos的name字段添加唯一索引</span>
db.userinfos.createIndex({name:<span style="color: rgba(128, 0, 128, 1)">1</span>},{unique:<span style="color: rgba(0, 0, 255, 1)">true</span>})</pre>
</div>
<p> 看一个使用唯一索引的栗子:</p>
<p><img style="border: 2px solid rgba(0, 0, 255, 1)" src="https://img2018.cnblogs.com/blog/1007918/201906/1007918-20190617224005485-827258022.png" alt=""></p>
<h3>2 局部索引</h3>
<p> 局部索引(Partial Indexes)顾名思义,只对collection的一部分添加索引。创建索引的时候,根据过滤条件判断是否对document添加索引,对于没有添加索引的文档查找时采用的全表扫描,对添加了索引的文档查找时使用索引。使用方法也比较简单:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">userinfos集合中age>25的部分添加age字段索引</span>
<span style="color: rgba(0, 0, 0, 1)"> db.userinfos.createIndex(
{age:</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">},
{ partialFilterExpression: {age:{$gt: </span><span style="color: rgba(128, 0, 128, 1)">25</span><span style="color: rgba(0, 0, 0, 1)"> }}}
)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询age<25的document时,因为age<25的部分没有索引,会全表扫描查找(stage:COLLSCAN)</span>
db.userinfos.find({age:<span style="color: rgba(128, 0, 128, 1)">23</span><span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询age>25的document时,因为age>25的部分创建了索引,会使用索引进行查找(stage:IXSCAN)</span>
db.userinfos.find({age:<span style="color: rgba(128, 0, 128, 1)">26</span>})</pre>
</div>
<p> 当查询age=23的记录时,stage=COLLSCAN,当查询age=26的记录时,使用了索引,如下:</p>
<p><img style="border: 2px solid rgba(0, 0, 255, 1)" src="https://img2018.cnblogs.com/blog/1007918/201906/1007918-20190616191305734-1488348448.png" alt=""></p>
<h3>2 稀疏索引</h3>
<p> 稀疏索引(sparse indexes)在有索引字段的document上添加索引,如在address字段上添加稀疏索引时,只有document有address字段时才会添加索引。而普通索引则是为所有的document添加索引,使用普通索引时如果document没有索引字段的话,设置索引字段的值为null。</p>
<p> 稀疏索引的创建方式如下,当document包含address字段时才会创建索引:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建在address上创建稀疏索引</span>
db.userinfos.createIndex({address:<span style="color: rgba(128, 0, 128, 1)">1</span>},{sparse:<span style="color: rgba(0, 0, 255, 1)">true</span>})</pre>
</div>
<p> 看一个使用稀疏索引的栗子:</p>
<p><img style="border: 2px solid rgba(0, 0, 255, 1)" src="https://img2018.cnblogs.com/blog/1007918/201906/1007918-20190617204220128-694064785.png" alt=""></p>
<h3>4 TTL索引</h3>
<p> TTL索引(TTL indexes)是一种特殊的单键索引,用于设置document的过期时间,mongoDB会在document过期后将其删除,TTL非常容易实现类似缓存过期策略的功能。我们看一个使用TTL索引的栗子:</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加测试数据</span>
<span style="color: rgba(0, 0, 0, 1)">db.logs.insertMany([
{_id:</span><span style="color: rgba(128, 0, 128, 1)">1</span>,createtime:<span style="color: rgba(0, 0, 255, 1)">new</span> Date(),msg:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">log1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">},
{_id:</span><span style="color: rgba(128, 0, 128, 1)">2</span>,createtime:<span style="color: rgba(0, 0, 255, 1)">new</span> Date(),msg:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">log2</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">},
{_id:</span><span style="color: rgba(128, 0, 128, 1)">3</span>,createtime:<span style="color: rgba(0, 0, 255, 1)">new</span> Date(),msg:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">log3</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">},
{_id:</span><span style="color: rgba(128, 0, 128, 1)">4</span>,createtime:<span style="color: rgba(0, 0, 255, 1)">new</span> Date(),msg:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">log4</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}
])
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在createtime字段添加TTL索引,过期时间是120s</span>
db.logs.createIndex({createtime:<span style="color: rgba(128, 0, 128, 1)">1</span>}, { expireAfterSeconds: <span style="color: rgba(128, 0, 128, 1)">120</span><span style="color: rgba(0, 0, 0, 1)"> })
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">logs中的document在创建后的120s后过期,会被mongoDB自动删除</span></pre>
</div>
<p> 注意:TTL索引只能设置在date类型字段(或者包含date类型的数组)上,过期时间为字段值+exprireAfterSeconds;document过期时不一定就会被立即删除,因为mongoDB执行删除任务的时间间隔是60s;capped Collection不能设置TTL索引,因为mongoDB不能主动删除capped Collection中的document。</p>
<p><strong>小结</strong></p>
<p> 本节介绍了mongoDB中常用的索引和索引属性,索引对提升数据检索的速度十分重要,在数据量比较大的时候一般都要在collection上建立索引。mongoDB提供的索引种类很丰富,总会有几种适用于我们的业务,除了上边介绍的索引外,mongoDB还支持text index和一些地理位置相关的索引,这里不再介绍,有兴趣的小伙伴可以到官网 研究下。如果文中有错误的话,希望大家可以指出,我会及时修改,谢谢。</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<div style="border: 2px solid #21759b; padding: 20px">
<div>作者:捞月亮的猴子</div>
<div>出处:https://www.cnblogs.com/wyy1234/</div>
<div>欢迎转载,但请标明出处。如果本文对您有些许帮助,点击一下推荐吧,Thanks♪(・ω・)ノ</div>
</div><br><br>
来源:https://www.cnblogs.com/wyy1234/p/11032163.html
頁:
[1]