乐趣区

关于后端:MongoDB-官方文档笔记之索引-Indexes

本文是在浏览 MongoDB 官网文档时记录的一些次要概念,更多细节能够查看文中的参考链接。

查看以后 db 索引

db.COLLECTION_NAME.getIndexes()

[
  {
    "v" : 1,
    "key" : {"_id" : 1},
    "name" : "_id_",
    "ns" : "newDB.sites"
  },
  {
    "v" : 1,
    "key" : {
      "name" : 1,
      "domain" : -1
    },
    "name" : "name_1_domain_-1",
    "ns" : "newDB.sites"
  }
]

单字段索引 single field

在单个字段上创立索引,1 示意升序,- 1 示意降序。

对于单字段索引来说,指定升序降序无关紧要,查问时抉择升序降序性能是一样的。

但对于复合索引来说,查问须要合乎索引的程序能力走上索引。

# 创立索引
db.records.createIndex({ score: 1} )

# 查问应用索引
db.records.find({ score: 2} )
db.records.find({ score: { $gt: 10} } )

嵌入式文档的外部字段上的索引

什么是嵌入式字段?就是这个字段的值也是一个文档。MongoDB 反对在嵌入式文档的外部字段上建设索引

# location 是一个文档
{"_id": ObjectId("570c04a4ad233577f97dc459"),
  "score": 1034,
  "location": {state: "NY", city: "New York"}
}

# 在 location 上面的 state 字段上创立索引
db.records.createIndex({ "location.state": 1} )

# 查问
db.records.find({ "location.state": "CA"} )
db.records.find({ "location.city": "Albany", "location.state": "NY"} )

在嵌入式文档自身建设的索引

还拿下面例子来讲,能够间接在 location 下面建设索引

{"_id": ObjectId("570c04a4ad233577f97dc459"),
  "score": 1034,
  "location": {state: "NY", city: "New York"}
}

# 间接在 location 上建设索引
db.records.createIndex({ location: 1} )

# 应用索引
db.records.find({ location: { city: "New York", state: "NY"} } )

复合索引 compound

在多个字段上建设的索引,需 别离指定每个字段的升降序规定。查问时须要合乎升降序规定或合乎反向规定,能力走上索引。

复合索引最多只能反对 32 个字段。

复合索引 反对前缀查问

# 文档构造
{"_id": ObjectId(...),
 "item": "Banana",
 "category": ["food", "produce", "grocery"],
 "location": "4th Street Store",
 "stock": 4,
 "type": "cases"
}

# 建设索引 以 item 升序 且 stock 升序简历索引。含意是,当文档的 item 值雷同时,按 stock 升序排序
db.products.createIndex({ "item": 1, "stock": 1} )

# 复合索引也反对前缀查问
db.products.find({ item: "Banana"} )
db.products.find({ item: "Banana", stock: { $gt: 5} } )

复合索引的索引程序

索引以升序(1)或降序(-1)排序顺序存储对字段的援用。对于单字段索引,键的排序程序无关紧要,因为 MongoDB 能够在任一方向上遍历索引。然而,对于复合索引,属性的程序决定了索引是否反对后果集的排序。

# 假如合乎索引如下
db.events.createIndex({ "username" : 1, "date" : -1} )

# 这个索引反对如下两种查问
db.events.find().sort( { username: 1, date: -1} )
db.events.find().sort( { username: -1, date: 1} )

# 但不反对上面的查问
db.events.find().sort( { username: 1, date: 1} )

# 即只能从索引一头儿查问能力走上索引

复合索引中的前缀索引

# 假如有如下复合索引
{"item": 1, "location": 1, "stock": 1}

# 则可反对上面两种前缀索引查问
{item: 1}
{item: 1, location: 1}

# 同时也反对前缀的局部匹配,即如下查问可用上 item 字段的前缀索引
{item: 1, stock: 1}

多键索引 multikey

反对对数组元素内的字段做索引。

# 如果 field 是一个数组,则主动建设多键索引,无需非凡指定
db.coll.createIndex({ <field>: < 1 or -1 >} )

但 mongodb 限度 不能够在过个数组上做复合索引

# 上面这种状况,不能够在 {a:1, b:1} 上做索引
{_id: 1, a: [ 1, 2], b: [1, 2], category: "AB - both arrays" }

文本索引 text

MongoDB 提供文本索引以反对对字符串内容的文本搜寻查问。text 索引能够蕴含任何值为字符串或字符串元素数组的字段。

# 在 comments 字段上建设文本索引
db.reviews.createIndex({ comments: "text"} )

# 在多个字段上建设 text 索引
db.reviews.createIndex(
   {
     subject: "text",
     comments: "text"
   }
 )

文本索引还能够设置反对的语言、管制相关性分数权重排序、限度条目等,更多查看 https://www.mongodb.com/docs/manual/core/index-text/

通配符索引

有时查问的维度可能不固定,会依照多个字段去查问

# 数据文档
{"userMetadata" : { "likes" : [ "dogs", "cats"] } }
{"userMetadata" : { "dislikes" : "pickles"} }
{"userMetadata" : { "age" : 45} }
{"userMetadata" : "inactive"}

# 能够建设通配符索引
db.userData.createIndex({ "userMetadata.$**" : 1} )

# 反对以下查问
db.userData.find({"userMetadata.likes" : "dogs"})
db.userData.find({"userMetadata.dislikes" : "pickles"})
db.userData.find({"userMetadata.age" : { $gt : 30} })
db.userData.find({"userMetadata" : "inactive"})

https://www.mongodb.com/docs/manual/core/index-wildcard/

2dsphere 和 2d 索引

别离是对计算相似地球的球体上的几何形态的查问的索引,和对存储为二维立体上的点的数据应用 2d 索引

https://www.mongodb.com/docs/manual/core/2dsphere/

https://www.mongodb.com/docs/manual/core/2d/

索引个性

unique 惟一索引

惟一索引确保索引字段不会存储反复值,默认状况下,MongoDB 在创立汇合期间在 _id 字段上创立一个惟一的索引。

# 单字段上创立惟一索引
db.members.createIndex({ "user_id": 1}, {unique: true} ) 

# 多字段上复合惟一索引
db.members.createIndex({ groupNumber: 1, lastname: 1, firstname: 1}, {unique: true} )

# 数组类型的多键索引
# 文档构造如下:{_id: 1, a: [ { loc: "A", qty: 5}, {qty: 10} ] }
# 建设索引
db.collection.createIndex({ "a.loc": 1, "a.qty": 1}, {unique: true} )

partial 局部索引

只对满足指定筛选器表达式的文档做索引,这样索引量更少,性能更高。

# 对 rating>5 的文档做索引
db.restaurants.createIndex({ cuisine: 1, name: 1},
   {partialFilterExpression: { rating: { $gt: 5} } }
)

sparse 稠密索引

只对含有索引字段的文档建设索引,字段值是空值也建设。

与之对应的非稠密索引,则是会对空缺字段存储空值。

因为稠密索引中有局部文档未被计入索引中,所以在稠密索引上 count 查问不精确

db.addresses.createIndex({ "xmpp_id": 1}, {sparse: true} )

其余索引个性:

  • ttl 有效期索引
  • 不辨别大小写索引

索引穿插 Index Intersection

指同时利用多个索引

# 两个独立索引
{qty: 1}
{status: 1, ord_date: -1}

# 上面的查问能够同时利用两个索引,也就是索引交加
db.orders.find({ qty: { $gt: 10} , status: "A" } )

索引交加跟复合索引很像:复合索引性能更高,要求更严格。索引交叉性能差一些,但更灵便。

# 复合索引如下
{status: 1, ord_date: -1}

# 复合索引反对如下查问
db.orders.find({ status: { $in: ["A", "P"] } } )
db.orders.find(
   {ord_date: { $gt: new Date("2014-02-01") },
     status: {$in:[ "P", "A"] }
   }
)

# 但无奈反对上面的查问
db.orders.find({ ord_date: { $gt: new Date("2014-02-01") } } )
db.orders.find({} ).sort({ ord_date: 1} )

# 如果建设两个独立的索引,则能够用到这两个索引的索引交加
{status: 1}
{ord_date: -1}

但有一种状况不能走索引穿插:当查问须要排序时,而排序字段不在查问谓词(查问字段)中时,无奈利用索引交加。

换句话说,只有在查问谓词中的字段可能组成索引交加的,能力利用索引交加。

# 有如下四种索引
{qty: 1}
{status: 1, ord_date: -1}
{status: 1}
{ord_date: -1}

# 这条无奈利用索引交加,查问中只有 qty,而按 status 排序
db.orders.find({ qty: { $gt: 10} } ).sort({ status: 1} )

# 这条能够利用,查问中 qty 和 status+ord_date 组成了索引交加
db.orders.find({ qty: { $gt: 10} , status: "A" } ).sort({ ord_date: -1} )

业务中应用复合索引还是索引交加,须要取决于零碎具体情况。

治理索引,索引的增删查改

https://www.mongodb.com/docs/manual/tutorial/manage-indexes/

掂量索引的应用状况

  • db.collection.explain() 查看执行打算
  • db.people.find({name: "John Doe", zipcode: { $gt: "63000"} }).hint({ zipcode: 1} ) 强制走某索引

索引策略:索引的应用和排序

字符串比拟时,须要思考字符串的字符集,须要与建设索引时统一能力走索引。

排序时,也合乎前缀匹配

复合索引反对正模式与反模式

本文由 mdnice 多平台公布

退出移动版