索引是一种数据结构[一语道破天机]。为数据建立合适的索引,查询时能够不断缩小范围,提高效率。MongoDB的索引数据结构为B-Tree或者是hash。和mysql这些数据库差不多,语言是相通的,数据库也都是相通的。
1.MongoDB的索引类型
1)Single Field
单字段索引
2)Compound Index
复合索引
3)Multikey Index
多键索引
4)Hashed Indexes
哈希索引
通过计算索引字段值的哈希值,其中只能为单字段创建哈希索引,不能为多字段创建哈希索引,这和mysql有点不一样,mysql中可以为多字段创建一个哈希索引。并且哈希索引的属性不能是unique key,毕竟计算哈希值是可能存在哈希冲突的
5)Geospatial Index
地理空间索引
6)Text Indexes
全文索引
上面的4) 5) 6)三种数据类型在mysql中也存在
单字段索引:为集合中的一个字段建立索引
复合索引:为集合中的多个字段建立索引
多键索引:为集合中的一个数组字段建立索引,数组中的所有字段都将建立独立的索引
比如说有这样一个集合:
{
userid:1,
score:100,
add:[
{zip:"10036",...},
{zip:"10037",...}
]
}
db.collection.createIndex({"score":1})
创建了单字段索引
db.collection.createIndex({"score":1,"userid":-1})
创建了复合索引
db.collection.createIndex({"add":1})
创建了多字段索引,add为一个数组。在mongodb中,如果一个字段为数组,系统将自动为该字段创建多键索引
db.collection.createIndex({"score":"hashed"})
创建了哈希索引
举个例子后索引类型的区别就明白了
2.MongoDB的索引属性
1)unique index 唯一索引 mondodb会自动创建一个唯一索引 _id
如果一个索引的索引属性为unique,则该字段如果是单一索引,则内容不能重读,如果是复合索引,则内容组合不能重复
2)partial index
部分索引
部分索引就是为满足条件的数据建立索引
建立部分索引的语法:
db.collection.createIndex(index,partialFilterExpression)
eg:
db.restaurants.createIndex(
{ cuisine: 1, name: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)
这里只会为满足rating>5的数据建立{ cuisine: 1, name: 1}索引
索引的命中,必须包含 partialFilterExpression才能命中,并且查找数据的集合为满足 partialFilterExpression集合的子集
eg:
db.restaurants.find( { cuisine: "Italian", rating: { $gte: 8 } } )
可以使用上索引>=8在>5的范围内
db.restaurants.find( { cuisine: "Italian", rating: { $lt: 8 } } )
db.restaurants.find( { cuisine: "Italian" } )
不可以使用上索引
partial index
部分索引属性是mongo中特有的,使用部分索引可以降低存储和维护成本
3)sparse index
稀疏索引
稀疏索引和部分索引有点类似,部分索引是3.2以后才出现的,官方文档推荐使用partial index代替使用sparse index的地方
如何创建稀疏索引
db.collection.createIndex({"a":1},{sparse:true})
它会为a字段加索引,如果文本中没有a字段,则将跳过,不会创建索引,这就是它为什么叫稀疏索引的原因,并不是为所有文本建立索引
它等同于下面创建部分索引的方式
db.collection.createIndex(
{"a":1},{ partialFilterExpression: { a: { $exists: true } } }
)
4)ttl index 定期自动删除指定索引的内容,适用于存储logs/event data/session的集合
ttl index是一种特殊的单字段索引
eg:db.collection.createIndex({"score":1},{expireAfterSeconds: 3600 })
这是错误的
如果该索引的属性为ttl index,则该索引的字段必须为一个date,或者是一个包含date的数组,否则,ttl index将不起作用
假设score字段值为date,那么该字段在3600s后自动被删除。也可以是一个时间,当到达那个时间时自动删除
ttl index的删除操作:
和redis、session差不都
一个后台线程去检查是否过期,然后有一个定时任务去清除过期索引,索引索引过期和删除索引有一个延迟。如果定时任务还没删除过期索引,此时访问该索引字段,应该会删除该索引?
网友评论