MongoDB索引

前言

在MongoDB中,索引通常能够极大的提高查询的效率。如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文档并选取那些符合查询条件的记录。如果有一个合适的索引来进行查询,则可以限制扫描文档的数量。
  索引是特殊的数据结构,存储在一个易于遍历读取的数据集合中,它是对数据库表中一列或多列的值进行排序的一种结构。索引条目的排序支持高效的匹配和基于范围的查询操作,同时,MongoDB可以通过使用索引返回排序后的结果。
  下面的示意图表明如何通过索引筛选和整理匹配的文档。($lt条件操作符表示小于,{score:-1或者1}表示逆向排序或者正向排序)

index-for-sort.png

  从本质上来说,MongoDB中的索引与其他数据库系统中的索引相类似,对于集合中的任何域或者子域都支持索引。

默认索引 _id

MongoDB在创建集合时,会在_id域创建一个唯一性的索引,即禁止插入两个具有相同_id值的文档,同时该索引无法被删除。

查询、创建、删除索引

//查询索引
db.集合名.getIndexes()
//创建索引
db. 集合名.createIndex( <key and index type specification>, <options> )
//删除索引
db.集合名.dropIndex(<key and index type specification>)

常见索引

  • 单键索引
    MongoDB支持用户对文档的一个域创建单键索引,进行操作时,排列顺序并不重要因为无论升序还是降序,MongoDB均能做遍历。
    假设有名为records的集合,其中有一个记录如下:
{ 
"_id": ObjectId("570c04a4ad233577f97dc459"), 
"userid": 1,
"score": 1034, 
"location": { state: "NY", city: "New York" }
}

创建单键索引举例:

//这里的1不是值,而是代表排序方向,即升序
db.records.createIndex( { score: 1 } )
index-ascending
  • 复合索引
    当查询条件不止一个时,即要查询的字段不止一个时,就需要创建复合索引,最大字段数为31。
    创建复合索引举例(排列原则为,先对userid进行排序,在userid相同的基础上,再对score进行排序):
db.collection.createIndex( {userid:1, score:-1} )
// 查询时,支持对多个字段查询,也支持对单个字段查询
db.collection.find( { userid: "aa1" } )
db.collection.find( { userid: "ca2", score: { $gt: 60} } )

index-compound-key

1)排序顺序:
假设一个集合events的文档有两个字段usernamedate,使用下面两条不同的语句查询:

db.events.find().sort( { username: 1, date: -1 } )
db.events.find().sort( { username: -1, date: 1 } )

可支持上面两条查询语句的索引为:

db.events.createIndex( { "username" : 1, "date" : -1 } )

但是,该索引却不支持下面的查询:

db.events.find().sort( { username: 1, date: 1 } )

更多详情可参考 Use Indexes to Sort Query Results(需翻墙)
2)前缀:
索引前缀是复合索引字段的子集。例如,考虑下面的复合:
{ "item": 1, "location": 1, "stock": 1 }
它的索引前缀为:

{ item: 1 }
{ item: 1, location: 1 }

该复合索引可查询的方法有如下几种:

the item field,
the item field and the location field,
the item field and the location field and the stock field.

当然还有the item field and the stock field,因为item field是一个索引前缀,当然这样的效率不及直接用item field and the stock field作为一个复合索引。
但是,下面的查询方法是不支持的,因为缺少了item字段而不符合索引前缀。

the location field,
the stock field,
the location and stock fields.

如果建立了复合索引,同时有一个单键索引与它的复合索引重复,当它们没有稀疏或者唯一的属性时,可把单键索引删去。因为MongoDB会在能使用复合索引前缀的任何情况下优先用之。

  • 多键索引
    多键索引和单键索引创建形式相同,区别在于字段的值。对于单键索引,字段的值为一个单一的值,如字符串,数字,日期。对于多键索引,值具有多个记录,如数组。为了给一个数组字段创建索引,MongoDB为数组中的每一个元素均创建一个索引键。多键索引支持高效查询数组字段,它可以被构建在包含字符串、数字类型或者嵌套文档的数组。
    创建多键索引举例:
db.collection.createIndex( { addr.zip: 1 } )

index-multikey

1)限制
多键索引不支持以下几种情况:分片键、哈希索引、覆盖查询。
对于复合多键索引,多个字段不能同时为数组,但允许其中一个字段为数组。
MongoDB无法直接使用整个数组作为查询条件,而是将数组的第一个元素作为查询条件,得到符合第一个元素的文档,返回给MongoDB,再使用第二个元素作为查询条件,直到得到最终结果。

  • 过期索引
    顾名思义,即在一段时间后便会过期的索引,在索引过期后,相应的数据会被删除。适合存储在一段时间之后会失效的数据比如用户的登录信息、存储的日志。
    创建过期索引举例(expireAfterSeconds后的值表示多少秒后删除):
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )

参考英文文档,由于英文水平不足,有些部分翻译会比较生硬。
如有建议,欢迎指出。

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容

  • 索引能够提高数据库的查询效率,没有索引的话,查询会进行全表扫描(scan every document in...
    zhglance阅读 2,029评论 0 6
  • 索引是数据库中的一个重要对象,主要用于支持高效查询操作。如果没有索引,数据库就只能进行全表扫描,效率将极为低下。m...
    UncleYee阅读 2,435评论 0 5
  • Mongodb索引及查询优化分析 创建索引 参数说明:keys: {FieldNameOne:ascending,...
    liudongdong阅读 4,298评论 1 8
  • 1、_id索引: 自动创建 2、单键索引: 【值为一个单个的值,例如字符串、数字或者日期】db.nums.in...
    Uzero阅读 769评论 2 0
  • MongoDB在创建集合的时候就在_id字段创建了一个唯一性索引. 这个索引防止客户端插入两个拥有相同_id的文档...
    Eve0阅读 414评论 0 0