稀疏索引(或者称间隙索引)就是只包含有索引字段的文档的条目,即使索引字段包含一个空值。也就是说间隙索引可以跳过那些索引键不存在的文档。因为他并非包含所有的文档,因此称为稀疏索引。与之相对的非稀疏索引或者说普通索引则包含所有的文档以及为那些不包含索引的字段存储null值。

一、间隙索引创建描述

    稀疏索引(或者称间隙索引)就是只包含有索引字段的文档的条目,跳过索引键不存在的文档
本文中后面的描述使用间隙索引 创建索引的语法:
db.collection.createIndex(keys, options) 创建间隙索引示例:
db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )
这个示例,哪些不包含xmpp_id的键(列)的文档将不会被索引 间隙索引不会被使用到的情形
如果一个间隙索引会导致查询或者排序操作得到一个不完整结果集的时候,MongoDB将不会使用这个索引,hint提示除外 哪些索引缺省情况就是间隙索引
2dsphere (version 2), 2d, geoHaystack, 文本索引等总是稀疏索引 间隙索引与唯一性
一个既包含稀疏又包含唯一的索引避免集合上存在一些重复值得文档,但是允许多个文档忽略该键。

二、间隙索引示例

1、创建间隙索引

    > db.version()
3.2.10 > db.scores.insertMany([
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" },
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 },
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }]) //下面为score键创建稀疏索引
> db.scores.createIndex( { score: 1 } , { sparse: true } ) > db.scores.find( { score: { $lt: 90 } } )
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
//由于文档newbie并不包含score键,因此该文档不会出现在稀疏索引之中,也就不会被查询返回 > //下面查询socre小于90文档的执行计划
> db.scores.find( { score: { $lt: 90 } } ).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.scores", //Author : Leshami
"indexFilterSet" : false, //Blog : http://blog.csdn.net/leshami
"parsedQuery" : {
"score" : {
"$lt" : 90
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN", //使用到了索引扫描
"keyPattern" : {
"score" : 1
},
"indexName" : "score_1", //索引为score_1
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : true, //此处表名为间隙索引
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"score" : [
"[-inf.0, 90.0)"
...........
"ok" : 1
}

2、间隙索引无法使用的示例

    > db.scores.find().sort( { score: -1 } )
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" } //从上面的查询结果可知,基于索引列score的排序返回了所有的文档
//这个排序真实的执行计划则是全表扫描,因为索引键并不包含不存在的用户id为newbie的文档
> db.scores.find().sort( { score: -1 } ).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.scores",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [ ]
},
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"score" : -1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "COLLSCAN", //使用了集合扫描方式
"filter" : {
"$and" : [ ]
},
"direction" : "forward"
}
............
"ok" : 1
}

3、强制间隙索引的示例

    //如果我们强制增加一个hint提示,则用户id为newbie的文档未被返回,即走了索引(执行计划此处略)
> db.scores.find().sort( { score: -1 } ).hint( { score: 1 } )
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }

4、间隙索引与唯一约束

    在唯一索引中,唯一索引会把null当做值,也就是说为null的通常只能有一个。后面的null将无法插入。
//下面创建一个带有唯一约束的稀疏索引
> db.scores.createIndex( { score: 1 } , { sparse: true, unique: true } )
{
"ok" : 0,
"errmsg" : "Index with name: score_1 already exists with different options",
"code" : 85
} //由于score列上已经存在一个索引了,因此提示我们,需要先删除,再创建 > db.scores.dropIndex("score_1")
{ "nIndexesWas" : 2, "ok" : 1 } > db.scores.createIndex( { score: 1 } , { sparse: true, unique: true } )
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
} //下面尝试插入一些带有score键以及不带有score键的文档,如下,可以成功插入
> db.scores.insert( { "userid": "AAAAAAA", "score": 43 } )
WriteResult({ "nInserted" : 1 })
> db.scores.insert( { "userid": "CCCCCCC" } )
WriteResult({ "nInserted" : 1 }) //下面插入一些score相关的文档,提示重复,如下示例
> db.scores.insert( { "userid": "AAAAAAA", "score": 82 } )
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.scores index: score_1 dup key: { : 82.0 }"
}
})
> db.scores.insert( { "userid": "BBBBBBB", "score": 90 } )
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.scores index: score_1 dup key: { : 90.0 }"
}
})

三、小结

a、间隙索引就是创建索引的索引列在某些文档上列不存在,导致索引存在间隙。 
b、间隙索引在创建时应指定选项:{ sparse: true } 
c、间隙索引列上可以指定唯一性约束

参见:http://blog.csdn.net/leshami/article/details/53897157

mongodb 稀疏索引的更多相关文章

  1. MongoDB的索引(三)

    MongoDB的索引: 1. _id索引 该索引是大多数集合默认创建的索引,也就是说用户每插入一个数据,MongoDB会自动生成一条唯一的_id字段. 2. 单键索引 单键索引是最普通的索引,它不会自 ...

  2. MongoDB数据库索引

    前面的话 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录.这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查 ...

  3. 五、MongoDB的索引

    一.MongoDB的下载.安装与部署 二.MongoDB的基础知识简介 三.MongoDB的创建.更新和删除 四.MongoDB的查询 五.MongoDB的索引 1.简介 它就像是一本书的目录,如果没 ...

  4. mongodb 的索引

                索引加快了查询速度,但是降低了写入速度.所以不要在没必要的属性上加索引.             在 mongodb 中索引可以按倒序/正序创建,便于排序.           ...

  5. 快速掌握mongoDB(三)——mongoDB的索引详解

    1 mongoDB索引的管理 本节介绍mongoDB中的索引,熟悉mysql/sqlserver等关系型数据库的小伙伴应该都知道索引对优化数据查询的重要性.我们先简单了解一下索引:索引的本质就是一个排 ...

  6. mongodb的索引原理

    首先说一下为什么要有索引,大家都知道mongdb是非关系型文档类型数据库,用过的人都有同一种感受,查询的效率太低,当你想提高查询效率的时候可以就需要使用索引了. 哈哈,本来想写一篇的,在网上看到了一篇 ...

  7. mongodb添加索引

    mongodb可以添加多列索引 稠密索引:该列中即使有null值也能给你查出来 稀疏索引:该列中查不出包含null值的列 二叉树索引是由码放的顺序的,哈希则是散列,相邻的数字,排列顺序并不一定紧邻

  8. mongodb的索引操作

    在mongodb中,当我们一个集合中的数据量非常大时,比如几百万条数据,如果不使用索引,对数据的查询就会进行全表扫描,这个时候查询的速度就会非常的慢,此时我们就需要为集合建立上索引,从而加快查询的速度 ...

  9. MongoDB 覆盖索引查询

    MongoDB 覆盖索引查询 官方的MongoDB的文档中说明,覆盖查询是以下的查询: 所有的查询字段是索引的一部分 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, Mo ...

随机推荐

  1. 一个KVO 实现WKWebView加载进度条的例子 (注意最后移除观察者)

    // // OpenWebViewController.m // Treasure // // Created by 蓝蓝色信子 on 16/7/29. // Copyright © 2016年 GY ...

  2. 2,ArrayList

    一,ArrayList简介 1,ArrayList 是一个数组队列,相当于动态数组.与Java中的数组相比,它的容量能动态增长. 2,ArrayList 继承了AbstractList,实现了List ...

  3. [Ynoi2012]D1T3

    https://www.luogu.org/problemnew/show/P5311 题解 先把点分树建出来. 对于吗,每一个询问\((l,r,x)\),我们对于x要找到它在点分树上最靠上的父亲节点 ...

  4. IDEA搭建spingboot项目

    1.Springboot2.x是依赖于JDK1.8及以上版本的.因此先在电脑上安装JDK1.8,由于公司的项目用的是JDK1.7,所以要在JDK1.7的基础上在安装JDK1.8,让两者同时存在于电脑上 ...

  5. ubuntu14编译安装qt5.0.1

    http://hi.baidu.com/houxn22/item/d652f29dec4a701f924f41a0 1.进入官网:http://qt-project.org/downloads下载对应 ...

  6. instanceof关键字用于判断一个引用类型变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例。

    http://lavasoft.blog.51cto.com/62575/79864/    深入Java关键字instanceof 2008-06-02 07:50:43 标签:Java 关键字 休 ...

  7. MySQL 查询语句--------------进阶7:子查询

    #进阶7:子查询 /* 含义: 出现在其他语句中的select语句,称为子查询或者内查询 外部的查询语句,称为主查询或外查询 分类: 按照子查询出现的位置: select后面:只支持标量子查询 fro ...

  8. Win7 VSCode 离线安装Rust语言及环境配置

    前置依赖 装过Visual Studio或Visual Studio Build Tool 2015 下载Rust离线安装包 https://forge.rust-lang.org/other-ins ...

  9. 关于VMware中的几个网络模式

    直接参考别人的: 写的已经很细致了: http://blog.csdn.net/yaoyaowugui/article/details/7422388 关键是看别人的几张图

  10. C# 压缩、解压缩

    /// <summary> /// 压缩文件 FNameArry 为客户端传回来的文件列表:文件名数组,压缩包的名称strZipName /// </summary> /// ...