索引数据库
索引一般可以极大的提升查询的效率。在系统中使用查询时,应该考虑创建相关的索引。在MongoDB中建立索引相对比较容易。数据结构
MongoDB中的索引在概念上和大多数关系型数据库如MySQL是同样的。当你在某种状况下须要在MySQL中创建索引,这样的情景一样适合于MongoDB。app
基本操做函数
索引是一种数据结构,他搜集一个集合中文档特定字段的值。MongoDB的查询优化器可以使用这种数据结构来快速的对集合(collection)中的文档(collection)进行寻找和排序.准确来讲,这些索引是经过B-Tree索引来实现的。post
在命令行中,能够经过调用ensureIndex()函数来创建索引,该函数指定一个到多个须要索引的字段。沿用在前面的随笔中的例子,咱们再things集合中的j字段上创建索引:性能
>
db.things.ensureIndex({j:
1
})
EnsureIndex()函数自是在索引不存在的状况下才会建立。大数据
一旦集合在某一个字段上创建索引后,对该字段的随机查询的访问速度会很快。若是没有索引,MongoDB会在遍历全部的键值对,而后去对应检查相关的字段。优化
>
db.things.find({j:
2
});
//
在创建了索引的字段上查询,速度快
{
"
_id
"
: ObjectId(
"
4e24433dcac1e3490b9033be
"
),
"
x
"
:
4
,
"
j
"
:
2
}
>
db.things.find({x:
3
});
//
在未创建索引的字段上查询,须要逐个字段匹配,速度慢
{
"
_id
"
: ObjectId(
"
4e244315cac1e3490b9033bc
"
),
"
x
"
:
3
}
经过在命令行中输入getIndexs()可以查看当前集合中的全部索引。spa
>
db.things.getIndexes()
[
{
"
name
"
:
"
_id_
"
,
"
ns
"
:
"
things.things
"
,
"
key
"
: {
"
_id
"
:
1
},
"
v
"
:
0
},
{
"
_id
"
: ObjectId(
"
4e244382cac1e3490b9033d0
"
ns
"
:
"
things.things
"
,
"
key
"
: {
"
j
"
:
1
},
"
name
"
:
"
j_1
"
,
"
v
"
:
0
}
]
经过db.system.indexes.find()可以返回当前数据库中的全部索引命令行
>
db.system.indexes.find()
{
"
name
"
:
"
_id_
"
,
"
ns
"
:
"
things.things
"
,
"
key
"
: {
"
_id
"
:
1
},
"
v
"
:
0
}
{
"
_id
"
: ObjectId(
"
4e244382cac1e3490b9033d0
"
),
"
ns
"
:
"
things.things
"
,
"
key
"
:{
"
j
"
:
1
},
"
name
"
:
"
j_1
"
,
"
v
"
:
0
}
默认索引
对于每个集合(除了capped集合),默认会在_id字段上建立索引,并且这个特别的索引不能删除。_id字段是强制惟一的,由数据库维护。
嵌套关键字
在MongoDB中,甚至可以在一个嵌入的文档上(embedded)创建索引.
>
db.things.ensureIndex({
"
address.city
"
:
1
})
文档做为索引
任何类型,包括文档(document)都能做为索引:
>
db.factories.insert({name:
"
xyz
"
,metro:{city:
"
New York
"
,state:
"
NY
"
}});
>
db.factories.ensureIndex({metro:
1
});
>
db.factories.find({metro:{city:
"
New York
"
,state:
"
NY
"
}});
//
可以利用索引进行查询
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find({metro:{$gte:{city:
"
New York
"
}}});
//
可以利用索引进行查询
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find({metro:{state:
"
NY
"
,city:
"
New York
"
}})
//
不可以返回结果,字段的顺序不对
建立文档索引的一个替代方法是建立复合索引,例如:
>
db.factories.ensureIndex({
"
metro.city
"
:
1
,
"
metro.state
"
:
1
})
>
db.factories.find({
"
metro.city
"
:
"
New York
"
,
"
metro.state
"
:
"
NY
"
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find({
"
metro.city
"
:
"
New York
"
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find().sort({
"
metro.city
"
:
1
,
"
New York
"
:
1
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
>
db.factories.find().sort({
"
metro.city
"
:
1
});
{
"
_id
"
: ObjectId(
"
4e244744cac1e3490b9033d2
"
),
"
name
"
:
"
xyz
"
,
"
metro
"
: {
"
cit
y
"
:
"
New York
"
,
"
state
"
:
"
NY
"
} }
组合关键字索引
除了基本的以单个关键字做为索引外,MongoDB也支持多个关键字的组合索引,和基本的索引同样,也是用ensureIndex()函数,该函数能够指定多个键。
>
db.things.ensureIndex({j:
1
,name:
-
1
})
当建立索引时,键后面的数字代表了索引的方向,取值为1或者-1,1表示升序,-1表示降序。升序或者降序在随机访问的时候关系不大,当时在作排序或者范围查询的时候就很重要了。
若是在创建了a,b,c这样一个复合索引,那么你能够在a,
A,b和a,b,c上使用索引查询。
稀疏索引
和稀疏矩阵相似,稀疏索引就是索引至包含被索引字段的文档。
任何一个稀疏的缺失某一个字段的文档将不会存储在索引中,之因此称之为稀疏索引就是说缺失字段的文档的值会丢失。
稀疏索引的建立和彻底索引的建立没有什么不一样。使用稀疏索引进行查询的时候,某些因为缺失了字段的文档记录可能不会被返回,这是因为稀疏索引子返回被索引了的字段。可能比较难以理解,不过看几个例子就好理解了。
>
db.people.ensureIndex({title:
1
},{sparse:
true
})
//
在title字段上创建稀疏索引
>
db.people.save({name:
"
Jim
"
})
>
db.people.save({name:
"
yang
"
,title:
"
prince
"
})
>
db.people.find();
{
"
_id
"
: ObjectId(
"
4e244dc5cac1e3490b9033d7
"
),
"
name
"
:
"
Jim
"
}
{
"
_id
"
: ObjectId(
"
4e244debcac1e3490b9033d8
"
),
"
name
"
:
"
yang
"
,
"
title
"
:
"
prince
"
}
>
db.people.find().sort({title:
1
})
//
自有包含有索引字段的记录才被返回
{
"
_id
"
: ObjectId(
"
4e244debcac1e3490b9033d8
"
),
"
name
"
:
"
yang
"
,
"
title
"
:
"
prince
"
}
>
db.people.dropIndex({title:
1
})
//
删除稀疏索引以后,全部的记录均显示
{
"
nIndexesWas
"
:
2
,
"
ok
"
:
1
}
>
db.people.find().sort({title:
1
})
{
"
_id
"
: ObjectId(
"
4e244dc5cac1e3490b9033d7
"
),
"
name
"
:
"
Jim
"
}
{
"
_id
"
: ObjectId(
"
4e244debcac1e3490b9033d8
"
),
"
name
"
:
"
yang
"
,
"
title
"
:
"
prince
"
}
惟一索引
MongoDB支持惟一索引,这使得不能插入在惟一索引项上已经存在的记录。例如,要保证firstname和lastname都是惟一的,命令以下
> db.things.ensureIndex({firstname:1,lastname:1},{unique:true})
缺失的键
当一个文档以惟一索引的方式保存到集合中去的时候,任何缺失的索引字段都会一null值代替,所以,不能在惟一索引上同时插入两条缺省的记录。以下:
>
db.things.ensureIndex({firstname:
1
}, {unique:
true
});
>
db.things.save({lastname:
"
Smith
"
});
>
db.things.save({lastname:
"
Jones
"
});
//
会产生错误,由于firstname会有两个null.
重复值:
惟一索引不可以建立在具备重复值的键上,若是你必定要在这样的键上建立,那么想系统将保存第一条记录,剩下的记录会被删除,只须要在建立索引的时候加上dropDups这个可选项便可
>
db.things.ensureIndex({firstname :
1
}, {unique :
true
, dropDups :
true
})
Dropping Indexes
删除一个特定集合上的索引:
>
db.collection.dropIndexes();
删除集合中的某一个索引:
db.collection.dropIndex({x:
1
, y:
-
1
})
也能够直接执行命令进性删除
db.runCommand({dropIndexes:
'
foo
'
, index : {y:
1
}})
//
删除集合foo中{y:1}的索引
//
remove all indexes:
db.runCommand({dropIndexes:
'
foo
'
, index :
'
*
'
})
//
删除集合foo中全部的索引
重建索引:
能够所用以下命令重建索引:
db.myCollection.reIndex()
//
same as:
db.runCommand( { reIndex :
'
myCollection
'
} )
一般这是没必要要的,可是在集合的大小变更很大及集合在磁盘空间上占用不少空间时重建索引才有用。对于大数据量的集合来讲,重建索引可能会很慢。
注:
-
MongoDB
中索引是大小写敏感的
-
当更新对象是,只有在索引上的这些key
发生变化时才会更新。着极大地提升了性能。当对象增加了或者必须移动时,全部的索引必须更新,这回很慢
。
-
索引信息会保存在system.indexes
集合中,
运行
db.system.indexes.find()
可以看到这些示例数据,
-
索引的字段的大小有最大限制,
目前接近800 bytes.
可在大于这个值的字段上创建索引是能够的,可是该字段不会被索引,这种限制在之后的版本中可能被移除。
索引的性能
索引使得能够经过关键字段获取数据,可以使得快速查询和更新数据。
可是,必须注意的是,索引也会在插入和删除的时候增长一些系统的负担。往集合中插入数据的时候,索引的字段必须加入到B-Tree中去,所以,索引适合创建在读远多于写的数据集上,对于写入频繁的集合,在某些状况下,索引反而有反作用。不过大多数集合都是读频繁的集合,因此集合在大多数状况下是有用的。
使用sort()而不须要索引
若是数据集合比较小(一般小于4M),使用sort()而不须要创建索引就可以返回数据。在这种状况下,作好联合使用limit()和sort();