• MongoDB—索引


    Index

    定义

    索引,一个单独的、存储在磁盘上的数据结构

    mongodb 的索引采用 B-tree 数据结构存储

    • 易于遍历,支持相等匹配和范围查询

    • 存储字段的值以及指向其所在文档的指针

      包含集合中所有文档的指针(包含数据表中所有记录的引用指针)

    • 按字段的值排序

    mongodb index

    • 在集合级别定义索引,支持在文档中的任何字段或子字段上建立索引
    • 给某个字段添加索引,可以快速找出在该字段有特定值的文档,提高查询速度
    • 如果没有索引,mongodb必须扫描集合中所有的文档,以选择那些符合查询条件的文档。一般而言,在查询文档时应避免扫描全部文档,这样会使查询速度非常慢
    • 建立索引可以缩小mongodb扫描文档的数量,提高查询速度
    • mongodb 可以返回基于索引排序的查询结果

    演示基于索引查询并排序

    _id

    • mongodb 默认会为文档创建一个_id 字段,并建立唯一索引
    • 不能删除建立在_id字段上的索引
    • 索引名称为 _id_

    创建索引

    db.collection.createIndex

    • 为集合创建索引

    • 如果索引(名称)已经存在,则不会再次创建

    • 除 collation 选项外,使用 不同的选项 不会创建 具有相同索引规范的 索引,也不会修改这些选项的值

      只能删除之前的索引,重新使用新的选项创建

    • 使用不同的 collation 选项,可以创建 多个 具有相同的索引规范的 索引,但是需要指定 唯一的 索引名称

      db.person.createIndex({name:1},{name:"a_c", collation:{locale:"fr"}})
      db.person.createIndex({name:1},{name:"a_b", collation:{locale:"fa"}})
      
    • 如果文档不包含指定的字段,则操作失败

    格式

    db.collection.createIndex(keys, options)
    
    • keys

      • 类型:Document
      • 描述:
        • 包含字段和值的文档,其中字段是索引键,值是该字段的索引类型

          判断索引是否相同根据索引的 keys,因此 keys 不同就代表索引不同

          • 用下划线连接组成默认索引名称

          • 同一个字段上只能创建一个相同类型的索引,可以创建多个不同类型的索引

            例如 {age:1} {age:-1} 两个keys不同,索引(名)不同

        • 索引类型包括:test、geospatial、hashed、ascending、descending

          排序规则

          • 值为 1,表示升序(ascending)
          • 值为 -1,表示降序(descending)
    • options

      • 类型:Document

      • 描述:创建索引的选项,不同类型的索引有特定于该类型的选项,以下为共有选项

        • background

          • 类型:布尔【4.2版本中被废弃】

          • 描述:是否在后台执行创建索引的过程,不阻塞对集合的操作

            • false【默认】

              不在后台创建

            • true

              后台创建

          • 4.2 版本中所有的索引构建,使用一个优化的构建过程,它只在构建过程的开始和结束时持有独占锁,构建过程中让步于读写操作

            4.2 版本会忽略该选项

          • 4.2 版本之前索引的构建的整个过程都会持有独占锁,阻塞数据库及其所有集合上的操作,直到操作完成,在后台创建索引不会持有独占锁

        • unique

          • 类型:布尔

          • 描述:

            • 是否创建具有唯一性的索引

              • true

                此索引具有唯一性,当索引重复时,不接受对文档的插入或更新

              • false【默认】

            • 不适用于 hashed 索引

        • name

          • 类型:字符串

          • 描述

            • 自定义索引名称

            • 如果不指定,mongodb将通过 下划线 连接 索引字段的名称和排序规则 生成一个索引名称

              例如在 { item : 1, quantity: -1 } 上创建的索引名称为 item_1_quantity_-1

            • 一旦创建不能修改,只能删除再重新创建

          4.2 版本之前,索引名最大长度为 127 字节,4.2版本开始取消该限制

        • partialFilterExpression

          • 类型:Document

          • 描述:仅为集合中符合条件的文档建立索引,降低创建和维护成本

        • sparse

          [spɑrs] 稀疏

          • 类型:布尔

          • 描述:仅为集合中具有指定字段的文档建立索引

            • true

              建立稀疏索引

            • false 【默认】

            zdsphere、2d、geoHaystack、text 默认为稀疏文档,忽略此选项

        • expireAfterSeconds

          • 类型:integer,单位 秒
          • 描述:用于 TTL 索引中 控制 文档保存在集合中的时间
        • storageEngine

          • 类型:Document
          • 描述:指定存储引擎配置

    Returns

    • 成功

      {
      	"createdCollectionAutomatically" : false,
      	"numIndexesBefore" : 3,
      	"numIndexesAfter" : 4,
      	"ok" : 1
      }
      
      • createdCollectionAutomatically 是否自动创建集合
      • numIndexesBefore 创建之前索引个数
      • numIndexesAfter 创建之后索引个数
      • ok:1 创建成功
    • 失败

      {
      	"ok" : 0,
      	"errmsg" : "Error: hashed indexes do not currently support array values",
      	"code" : 16766,
      	"codeName" : "Location16766"
      }
      
      • ok:0 创建失败
      • errmsg 失败信息
      • code 失败码
      • codeName ?

    查询索引

    db.collection.getIndexes

    • 查询集合中所有的索引信息

    • 返回一个数组,数组元素是描述索引信息的文档

      索引信息包括创建索引时的信息:keys 以及 options

    格式

    db.collection.getIndexes()
    

    db.collection.totalIndexSize

    • 查询集合中所有索引的大小
    • 如果索引使用前缀压缩 (这是WiredTiger的默认值),则返回压缩后的大小
    • 单位 字节 byte

    格式

    db.collection.totalIndexSize()
    

    删除索引

    db.collection.dropIndex

    • 删除指定索引
    • 不能删除默认创建在 _id 字段上的索引

    格式

    db.collection.dropIndex(index)
    
    • index

      • 类型:字符串、文档

      • 描述:指定要删除的索引

        • 可以指定索引的名称 或 索引规范文档

          通过 db.collection.getIndexes() 获取索引名称

        • 删除 text 类型的索引,必须指定索引名称

          无法通过索引规范文档找到索引,删除失败

        • 4.2 版本开始,不能通过db.collection.dropIndex("*") 删除所有非 _id 字段上的索引,应该使用db.collection.dropIndexes()

    排它锁

    • 4.2 版本之前,dropIndex 操作在父级数据库上获取一个排它锁,阻塞所有对数据库及其所有集合的操作,直到操作完成
    • 4.2 版本之后,dropIndex 操作在指定集合上获取一个排它锁,阻塞对集合的所有后续操作

    示例

    • 通过索引名称删除

      db.pets.dropIndex( "cat_-1" )
      
    • 通过索引规范文档删除

      db.pets.dropIndex( { "cat" : -1 } )
      

    de.collection.dropIndexes

    • 删除单个或多个索引
    • 不能删除默认创建在 _id 字段上的索引

    格式

    db.collection.dropIndex(indexes)
    
    • indexes

      • 类型:字符串、文档、字符串数组

      • 描述:需要删除的索引

        • 删除_id 之外的所有索引,忽略该参数

        • 删除单个索引,指定索引的名称或索引规范文档,text 类型的索引只能指定名称

        • 删除多个索引,通过数组指定索引的名称

          如果数组中包含不存在的索引,则不删除任何索引,操作报错

          4.2 新增

    排它锁

    • 4.2 版本之前,dropIndex 操作在父级数据库上获取一个排它锁,阻塞所有对数据库及其所有集合的操作,直到操作完成
    • 4.2 版本之后,dropIndex 操作在指定集合上获取一个排它锁,阻塞对集合的所有后续操作

    示例

    • 删除_id之外的所有索引

      db.collection.dropIndexes()
      
    • 删除单个索引

      db.collection.dropIndexes( { a: 1, b: 1 } )
      
      db.collection.dropIndexes( "a_1_b_1" )
      
    • 删除多个索引

      db.collection.dropIndexes( [ "a_1_b_1", "a_1", "a_1__id_-1" ] )
      

    索引类型

    Single Field 索引

    • 单字段索引
    • 对于单字段索引,升序降序并不重要,因为mongodb可以按任意方向遍历索引

    示例

    db.collection.createIndex( { orderDate: 1 } )
    
    • 在 orderDate 字段上创建一个升序索引
    • 默认名称orderDate_1

    Compound 索引

    • 复合索引

    • 将多个字段组合成一个索引

    • 创建复合索引时,字段的顺序非常重要

    • 整体上按第一个字段进行排序,对于按第一个字段排序并列的索引,再使用第二个字段进行排序

    • 查询条件中必须包含索引的前缀字段

      例如以3个字段组成的索引,查询条件中需包含第一个字段 或 第一个及第二个字段 或 全部三个字段

    • 复合索引中不能包含 hashed 索引

    示例

    db.collection.createIndex( { orderDate: 1, zipcode: -1 } )
    
    • 创建一个在 orderDate 字段进行升序排列,在 zipcode 字段进行降序排列的复合索引

    Multikey 索引

    • 多键索引
    • 使用点表示法,对嵌套数组中的字段建立索引
    • mongodb会为数组中的每个元素创建单独的 索引项
    • 允许查询条件匹配数组的一个或多个元素来选择符合条件的文档
    • 如果索引字段包含数组元素,mongodb会自动创建一个多键索引

    Geospatial 索引

    • 地理空间索引

    Text 索引

    • 文本索引:对字符串内容进行查询
    • 一般在 字符串类型字段 或 字符串数组类型字段 上创建文本索引
    • 使用文本索引查找时,不区分字母大小写
    • 目前不支持中文文本索引,支持英语、法语、德语、俄语、西班牙语、土耳其语
    • 文本索引具有 sparse 属性,忽略创建过程中的 sparse 选项
    • 文本索引支持 $text 查询操作
    • 限制
      • 一个集合最多只能创建一个文档索引
      • 排序操作 sort,不能使用文本索引中的排序
      • 复合文本索引中,如果在文本索引键之前包含其他键,则通过 $text 搜索时,查询谓词必须包含前面键的相等匹配条件
      • 只能通过索引名称删除文本索引

    格式

    db.collection.createIndex(
    keys ,
    options
    )
    
    • keys

      • 类型:Document

      • 描述:text 类型的索引规范文档

        • 单字段

          { field1: "text"}
          
        • 多字段

          { 
          	field1: "text",
          	field2: "text",
          	...
          }
          // 复合索引
          { 
          	field1: 1,
          	field2: "text",
          	...
          }
          
        • 全部字段

          $** 代表文档中的所有字符串类型的字段

            { "$**": "text" }
          
    • options

      • weights
        • 类型:Document
        • 描述:
          • 包含字段和权重的文档,指定字段的权重,默认值为1,可设定为 1-99999 之间的整数
          • 优先查询权重大的字段,次之查询权重小的字段
      • default_language
        • 类型:字符串
        • 描述
          • 对于文本索引,不同的语言有不同的分析规则
          • 默认值为 english
      • language_override
        • 类型:字符串
        • 描述
          • For text indexes, the name of the field, in the collection’s documents, that contains the override language for the document
          • 默认值为language
      • textIndexVersion
        • 类型:integer
        • 描述:指定文本索引的版本

    示例

    • 创建文本索引

      db.reviews.createIndex( { comments: "text" } )
      
      db.reviews.createIndex(
         {
           subject: "text",
           comments: "text"
         }
       )
       
       db.reviews.createIndex( { "$**": "text" } )
      
    • 指定不同的权重

       db.reviews.createIndex(
       { "$**": "text" } ,
       { weights : {subject: 10, comments: 5}}
       )
      
      • 索引名$**_text

    Hashed 索引

    • 哈希索引:使用字段值的哈希值来创建索引

    • 主要用在分片的片键上

    • 支持 非数组 单字段 索引,不支持多字段索引

      多字段索引报错

      db.articles.createIndex({subject:"hashed",author:"hashed"})
      
      • "errmsg" : "Currently only single field hashed index supported."

      数组字段索引报错

      db.articles.createIndex({arr:"hashed"})
      
      • "errmsg" : "Error: hashed indexes do not currently support array values",

      • creating a hashed index on a field that contains an array or attempting to insert an array into a hashed indexed field returns an error.

    • 不能设定唯一性约束,因为存在hash碰撞

      db.articles.createIndex({subject:"hashed"},{unique:true})
      
      • "errmsg" : "Currently hashed indexes cannot guarantee uniqueness. Use a regular index."
    • 创建哈希索引的字段,也可以同时创建其他索引

      不支持创建复合索引,但是同一个字段可以创建多个不同类型的索引

      db.articles.createIndex({subject:"hashed"})
      db.articles.createIndex({subject:"hashed",subject:"text"}) // 只会创建一个文本索引
      db.articles.createIndex({subject:"hashed",subject:1}) // 只会创建一个升序索引
      // 最终在 subject 字段上创建了3个不同类型的索引
      
    • 哈希索引支持相等查询,不支持范围查询

    • 在使用哈希索引查询时,mongodb 会自动计算,无需单独计算

      4.0 版本开始,mongodb提供了 convertShardKeyToHashed() 方法,该方法使用相同的哈希计算方法,可用于查看键的哈希值

    • 类型为浮点数的字段不能创建哈希索引

      mongodb 哈希索引在计算之前会将浮点数截断为64位的整数,例如 2.3、 2.2、 2.9 都被截断为2进行计算

    格式

    db.collection.createIndex( { field: "hashed" } )
    

    索引属性

    Unique 索引

    • 唯一性

    Partial 索引

    • 局部性

    Sparse 索引

    • 稀疏性

    TTL 索引

    • 生命周期性(文档在一段时间后会被mongodb自动删除)

    • 一般在 Date类型的字段 或 包含Date类型元素的数组字段 上创建TTL索引,其他字段无效

    • 过期阈值的计算

      • 如果字段类型是 Date,则过期阈值是字段值日期加上指定的过期时间
      • 如果字段类型是包含 Date 类型元素的数组,则过期阈值是元素中最早的日期加上指定的过期时间
      • 如果非以上两种类型,TTL 索引无效,文档不会过期
    • expireAfterSeconds 设置为0,则过期时间就是日期字段的值

    • TTL 线程

      • mongod 中的后台线程,每隔60秒运行一次,用来读取索引中的值并从集合中删除过期的文档
      • 不保证文档过期后立即被删除,文档过期的时间和从数据库中删除的时间存在延迟(60s)
      • 当 TTL 线程处于活动状态时,可以在 db.currentOp() 的输出中看到删除操作
    • 限制

      • 不能在 _id 字段上建立 TTL 索引

      • 不能通过改变 options 将非 TTL 索引变为 TTL 索引

      • 不能在固定集合中建立 TTL 索引,因为mongodb不能从固定集合中删除文档

      • 不能是复合索引,只能是单字段索引

    格式

    db.collection.createIndex(
        <keys>,
        {
        expireAfterSeconds: <integer>
        }
    )
    

    示例

    文档

    db.ttl.insertMany([
    {date:new Date("2020-08-13T17:50:00"), money:1},
    {date:new Date("2020-08-13T17:52:00"), money:2},
    {date:new Date("2020-08-13T17:54:00"), money:3},
    ])
    
    db.ttl.createIndex({date:-1})
    db.ttl.createIndex({date:1, money:-1})
    db.ttl.createIndex({date:1},{expireAfterSeconds:10})
    
    • 在 ttl 集合中的 date 字段上创建3个索引
    • 有一个 TTL 索引,过期阈值为:date 日期加上指定过期时间
    • 结果是,到过期阈值时,文档被依次删除

    修改过期时间

    db.runCommand({
       collMod: <collection>,
       index:{
                  keyPattern: <keys>,
                  expireAfterSeconds: <integer>
        }
    })
    

    示例

    db.ttl.insertMany([
    {date:new Date("2020-08-13T18:08:00"), money:1},
    {date:new Date("2020-08-13T18:09:00"), money:2},
    {date:new Date("2020-08-13T18:10:00"), money:3},
    ])
    
    db.runCommand({
    	collMod:"ttl",
    	index:{
    		keyPattern:{date:1},
    		expireAfterSeconds:60*60
    	}
    })
    

    返回结果

    { "expireAfterSeconds_old" : 10, "expireAfterSeconds_new" : 3600, "ok" : 1 }
    

    Hidden 索引

    4.4 新增

    • 对查询规划器不可见,不能用于查询
    • 用来评估删除索引的潜在影响,而不必实际删除该索引。如果影响是负面的,用户可以取消隐藏索引,而不必重新创建
    • 索引在隐藏时也会被维护,因此一旦不隐藏,就可以立即使用这些索引
  • 相关阅读:
    【poj1182】 食物链
    【bzoj1013】 JSOI2008—球形空间产生器sphere
    【codevs1200】 NOIP2012—同余方程
    【poj2891】 Strange Way to Express Integers
    【bzoj2819】 Nim
    【bzoj2463】 谁能赢呢?
    【poj3537】 Crosses ans Crosses
    【bzoj2115】 Xor
    下载时出现using cached如何解决
    如何设计一个"好的"测试用例?
  • 原文地址:https://www.cnblogs.com/usmile/p/13576813.html
Copyright © 2020-2023  润新知