Skip to content

Latest commit

 

History

History
268 lines (183 loc) · 10 KB

索引.md

File metadata and controls

268 lines (183 loc) · 10 KB

索引

自然排序

  1. 对于固定集合可以进行一种特殊的排序, 称为自然排序。自然排序返回结果集中文档的顺序就是文档在磁盘上的顺序。 使用 {"$natural":1} 进行排序。

  2. 对于大多数集合来说, 自然排序的意义不大, 因为文档的位置经常变动。但是,固定集合中的文档 是按照文档被插入的顺序保存的。自然顺序就是文档的 插入顺序。

    //按照自然顺序的正序排序
    db.log.find().sort({"$natural":1});
    //按照自然顺序的倒序排序
    db.log.find().sort({"$natural":-1});

查看索引

db.collection.getIndexKeys() /*查看集合创建的索引信息*/

索引类型

普通键索引

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

#创建正序的索引
db.records.createIndex({score:1},{name:"scoreAscIndex"})
#创建倒序的索引
db.records.createIndex({score:-1},{name:"scoreDescIndex"})

嵌入的文档建立索引

  1. 创建索引

    //通过 . 的这种操作对嵌入的文档建立索引
    db.records.createIndex( { "location.state": 1 },{name:"stateIndex"} )
    
  2. 下面的查询可以用到这个索引

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

唯一索引

  1. 创建索引

    db.index.createIndex({"name":1},{"unique":true}) #创建一个唯一索引
    

稀疏索引

  1. 密集索引 和 稀疏索引的概念

    • 密集索引:mongodb索引默认是密集型的。在一个有索引的集合里,每个文档都会有对应的索引项,哪怕文档中没有被索引键也是如此。例如,给文档的name字段建索引,而有的文档并没有name字段,那么name字段索引里会有null值,可以这样查询name为null值的文档:db.index.find({name: null})。
    • 稀疏索引仅包含具有索引字段的文档的条目,即使索引字段包含空值也是如此。索引会跳过缺少索引字段的任何文档。索引是“稀疏的”,因为它不包含集合的所有文档。
  2. 使用场景

    • 唯一索引会把null看做值, 所以无法 将多个缺少唯一索引中的键的文档插入到集合中. 然而, 在有些情况下, 可能希望唯一索引值对包含相应键的文档生效. 这时可以将 unique 和 sparse 选项组合在一起使用。

      db.index.createIndex({"name":1},{"unique":true,"sparse":true});
      
    • 集合中大量文档都不包含被索引键。

复合索引

  1. 创建索引

    db.collection.createIndex( { <field1>: <type>, <field2>: <type2>, ... } )  
    db.collection.createIndex({"title":1,"description":-1},{name:"title_desc"})
    
  2. 排序

    • 索引以升序(1)或降序(-1)排序顺序存储对字段的引用。对于单字段索引,键的排序顺序无关紧要,因为MongoDB可以在任一方向上遍历索引。但是,对于复合索引,排序顺序对于确定索引是否可以支持排序操作很重要。
    • 只有基于多个查询条件进行排序时,索引方向才是比较重要的。如果只是基于单一键进行排序,MongoDB可以简单地从相反方向读取索引。
  3. 示例

    这样的查询
    	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 })
    

覆盖索引

为了确保查询只是用索引就可以完成,应该使用投射来制定不要返回 “_id” 字段 ( 除非它是索引的一部分)。可能需要对不需要查询的字段做索引。

地理空间索引

创建空间位置索引 https://blog.csdn.net/zhangzhebjut/article/details/23021073

TTl索引

  1. TTL索引是一种特殊索引,通过这种索引MongoDB会过一段时间后自动移除集合中的文档。这对于某些类型的信息来说是一个很理想的特性,例如机器生成的事件数据,日志,会话信息等,这些数据都只需要在数据库中保存有限时间。

  2. 数据到期

    • TTL索引在索引字段值超过指定的秒数后过期文档; 即,到期阈值是索引字段值加上指定的秒数。
    • 如果字段是数组,并且索引中有多个日期值,则MongoDB使用数组中的最低(即最早)日期值来计算到期阈值。
    • 如果文档中的索引字段不是日期 或包含日期值的数组,则文档将不会过期。
    • 如果文档不包含索引字段,则文档不会过期
  3. 创建

    //创建一个10秒以后自动删除
    db.log.createIndex({"cTiem":1},{expireAfterSeconds:10});
    //写入数据
    db.log.createIndex({"cTime":1},{expireAfterSeconds:10})
  4. 删除操作

    1. 当您在后台构建TTL索引时,TTL线程可以在索引构建时开始删除文档。如果您在前台构建TTL索引,MongoDB会在索引完成构建后立即开始删除过期的文档。
    2. TTL索引不保证在到期时立即删除过期数据。文档到期的时间与MongoDB从数据库中删除文档的时间之间可能存在延迟。
    3. 删除过期文档的后台任务每60秒运行一次。结果,文档可能在文档到期和后台任务运行之间的期间保留在集合中。
    4. 由于删除操作的持续时间取决于 mongod 实例的工作负载,因此在后台任务运行之间的60秒时间之后,过期数据可能会存在一段时间。

部分索引

  1. 部分索引仅索引符合指定过滤器表达式的集合中的文档。通过索引集合中的文档子集,部分索引具有较低的存储要求,并降低了索引创建和维护的性能成本。

  2. 适用范围

    • 等于的表达式。(示例:field:value 或者 $eq
    • $exists:true 表达式
    • $gt , $gte , $lt , $lte 表达式
    • $type 表达式
    • $and 表达式
  3. 创建

    复合索引
    db.restaurants.createIndex(
       { cuisine: 1, name: 1 },
       { partialFilterExpression: { rating: { $gt: 5 } } }
    )
    单键索引
    db.restaurants.createIndex(
       { cuisine: 1 },
       { partialFilterExpression: { rating: { $gt: 5 } } }
    )
    
    可以使用索引的查询语句
    db.restaurants.find( { cuisine: "Italian", rating: { $gte: 8 } } )
    
    不能使用索引的查询语句
    db.restaurants.find( { cuisine: "Italian", rating: { $lt: 8 } } )

管理索引

  1. 查看某给集合都使用了那些索引

    db.users.getIndexes();
  2. 查看索引是否创建成功

    db.getLastError();
  3. 强制指定使用那个索引

    db.books.find({"name":"0book"}).hint(name:-1);
  4. 重建索引

    db.collection.reIndex()	# 重建集合上的所有现有索引。
    
  5. 如果总体选择性较低,并且如果MongoDB必须读取大量文档以返回结果,那么一些查询可能在没有索引的情况下执行得更快。

查看索引大小

db.red.totalIndexSize() #单位:字节

db.red.stats();			#查看集合信息

删除索引

  1. 删除集合单个索引

    db.accounts.dropIndex({ "tax-id": 1 })
    
  2. 删除集合中除 _id 所有索引

    db.accounts.dropIndexes()
    

后台创建索引

  1. 默认情况下,在已填充的集合上创建索引会阻止数据库上的所有其他操作。在填充的集合上构建索引时,在索引构建完成之前,保存集合的数据库不可用于读取或写入操作。任何需要对所有数据库(例如listDatabases)进行读或写锁定的操作都将等待前台索引构建完成。

  2. 可以在创建索引时指定 background 选项. 这样在创建索引时, 如果有新的数据库请求需要处理, 创建索引的过程就会暂停一下, 但仍然会对应用程序影响较大。

    db.people.createIndex( { zipcode: 1 }, { background: true } )

索引策略

使用索引对查询结果进行排序

  1. 在MongoDB中,排序操作可以通过基于索引中的排序检索文档来获取排序顺序。如果查询计划程序无法从索引获取排序顺序,它将在内存中对结果进行排序。使用索引的排序操作通常比不使用索引的排序操作具有更好的性能。此外,使用索引的排序操作将在使用32兆字节的内存时中止。

  2. 如果排序键对应于索引键或索引前缀,MongoDB可以使用索引对查询结果进行排序。甲前缀的化合物指数的是,在索引关键字模式的开始包括一个或多个键的子集。

    创建的索引
    	db.data.createIndex( { a:1, b: 1, c: 1, d: 1 } )
    查询可以使用
        db.data.find().sort( { a: 1 } )								{ a: 1 }
        db.data.find().sort( { a: -1 } )							{ a: 1 }
        db.data.find().sort( { a: 1, b: 1 } )						{ a: 1, b: 1 }
        db.data.find().sort( { a: -1, b: -1 } )						{ a: 1, b: 1 }
        db.data.find().sort( { a: 1, b: 1, c: 1 } )					{ a: 1, b: 1, c: 1 }
        db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } ) 	{ a: 1, b: 1 }
    
  3. 索引可以支持对索引键模式的非前缀子集的排序操作。为此,查询必须 在排序键之前的所有前缀键上包含相等条件。

    创建的索引
    	{ a: 1, b: 1, c: 1, d: 1 }
    查询可以使用
        db.data.find( { a: 5 } ).sort( { b: 1, c: 1 } )	{ a: 1 , b: 1, c: 1 }
        db.data.find( { b: 3, a: 4 } ).sort( { c: 1 } )	{ a: 1, b: 1, c: 1 }
        db.data.find( { a: 5, b: { $lt: 3} } ).sort( { b: 1 } )	{ a: 1, b: 1 }
    
  4. 要使用索引进行字符串比较,操作还必须指定相同的排序规则。也就是说,如果操作指定了不同的排序规则,则具有排序规则的索引不能支持对索引字段执行字符串比较的操作。