MongoDB索引Index分类及其实现原理


  与MySQL一样,MongoDB中也使用索引提高查询效率。那索引是什么呢?索引是?种单独的、物理的对数据库表中?列或多列的值进?排序的?种存储结构,它是某个表中?列或若?列值的集合和相应的指向表中物理标识这些值的数据?的逻辑指针清单。索引的作?相当于图书的?录,可以根据?录中的?码快速找到所需的内容。索引?标是提?数据库的查询效率,没有索引的话,查询会进?全表扫描(scan every document in a collection) ,数据量?时严重降低了查询效率。

  默认情况下Mongo在?个集合(collection)创建时,?动地对集合的_id创建了唯?索引。MongoDB中索引类型如下:

  1、单键索引 (Single Field)

    MongoDB?持所有数据类型中的单个字段索引,并且可以在?档的任何字段上定义。对于单个字段索引,索引键的排序顺序?关紧要,因为MongoDB可以在任??向读取索引。

    单个例上创建索引:

      db.collection_name.createIndex({"字段名":排序?式})

      

       1表示升序,-1表示降序。

    需要注意的是:MongoDB中有一个特殊的单键索引 ——过期索引 TTL Time To Live)。TTL索引是MongoDB中?种特殊的索引, 可以?持?档在?定时间之后?动过期删除,?前TTL索引只能在单字段上建?,并且字段类型必须是?期类型。

      db.collection_name.createIndex({"?期字段":排序?式}, {expireAfterSeconds: 秒数})

  2、复合索引(Compound Index

    实际生产中通常需要在多个字段的基础上搜索表/集合,这是?常频繁的。 如果是这种情况,可能会考虑在MongoDB中制作复合索引。 复合索引?持基于多个字段的索引,这扩展了索引的概念并将它们扩展到索引中的更?域。

    制作复合索引时要注意的重要事项包括:字段顺序与索引?向。
      db.collection_name.createIndex( { "字段名1" : 排序?式, "字段名2" : 排序?式 } )

  3、多键索引(Multikey indexes

    针对属性包含数组数据的情况, MongoDB?持针对数组中每?个element创建索引, Multikey indexes?持stringsnumbersnested documents。

  4、地理空间索引(Geospatial Index

    针对地理空间坐标数据创建索引。
      1)2dsphere索引,?于存储和查找球?上的点
      2)2d索引,?于存储和查找平?上的点
      

  5、全?索引

    全文索引是MongoDB提供的专门针对string内容的?本查询, Text Index?持任意属性值为stringstring数组元素的索引查询。需要注意的是:?个集合仅?持最多?个Text Index,中?分词不理想 推荐ES。

      db.collection_name.createIndex({"字段": "text"})
      db.collection_name.find({"$text": {"$search": "coffee"}})

  6、哈希索引 Hashed Index

    该索引针对属性的哈希值进?索引查询,当要使?Hashed index时, MongoDB能够?动的计算hash值,?需程序计算hash值。

      db.collection_name.createIndex({"字段": "hashed"})

    注意: hash index仅?持等于查询,不?持范围查询。

   通过以上索引分类,对比MySQL索引分类()差别还是相当大的。

  另外通过db.mycoll.help可以查看集合相关的方法。上面已经实践了索引的建立,那索引的查看、修改、删除等分别是用什么方法呢?下面揭晓:

    创建索引并在后台运?

      db.collection_name.createIndex({"字段":排序?式}, {background: true});
    获取针对某个集合的索引

      db.collection_name.getIndexes()
    索引的??

      db.collection_name.totalIndexSize()
    索引的重建

      db.collection_name.reIndex()
    索引的删除

      db.collection_name.dropIndex("INDEX-NAME")
      db.collection_name.dropIndexes()

    需要注意的是:_id 对应的索引是删除不了的(这个系统根据_id会自动创建索引)

  MongoDB中索引如何实现的呢?
关于索引的实现原理与MySQL索引实现原理对比进行分析:MySQL是关系型数据库,数据的关联性是?常强的,区间访问是常?的?种情况,底层索引组织数据使?B+树, B+树由于数据全部存储在叶?节点,并且通过指针串在?起,这样就很容易的进?区间遍历甚?全部遍历。 MongoDB使?B-树,所有节点都有Data域,只要找到指定索引就可以进?访问,单次查询从结构上来看要快于MySQL。

  对于B-树及B+树的结构在已经有详细的介绍,可以看出最核?的区别主要有俩:?个是数据的保存位置,?个是相邻节点的指向。就是这俩造成了MongoDBMySql的差别:

    1) B+树相邻接点的指针可以??增加区间访问性,可使?在范围查询等,?B-树每个节点 key 和 data 在?起适合随机读写 ,?区间查找效率很差。

    2) B+树更适合外部存储,也就是磁盘存储,使?B-结构的话,每次磁盘预读中的很多数据是?不上的数据。因此,它没能利?好磁盘预读的提供的数据。由于节点内? data 域,每个节点能索引的范围更?更精确。

    3)注意这个区别相当重要, B-树每个节点即保存数据?保存索引导致树的深度?,所以磁盘IO的次数多, B+树只有叶?节点保存,较B树??深度?,磁盘IO少,有利于区间访问。