MongoDB索引

        MongoDB提供了许多不同的方法,可以在其中形成索引并将其存储在内存(和磁盘)中。 这些索引中的每一个都有不同的用途,可能仅适用于某些数据类型。 我们来看看这些索引类型。

1、索引类型

1.1    单字段索引

        MongoDB支持所有数据类型中的单个字段索引,并且可以在文档的任何用户定义字段上定义。

        需要注意的是,对于单个字段索引,索引键的排序顺序无关紧要,因为MongoDB可以在任一方向读取索引。

1.2    复合索引

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

        制作复合索引时要注意的重要事项包括:字段顺序与索引方向。

1.2.1    字段顺序

        文档建立复合索引后,复合索引树会按复合索引里的字段顺序进行排序,如(a,b)索引,会先按a排序,再按b排序。

        复合索引内字段顺序,取决于查询语句的字段排序:

        1)如果我们的查询语句需要对a进行排序,b只是用于覆盖索引,那么建(a,b)索引;也即,如果建(a,b)索引,用a查询可以用上索引,用b查询是用不上索引的,这个也符合复合索引字段的前置优先规则。

        2)如果我们的查询语句需要对b进行排序,a只是用于覆盖索引,那么建(b,a)索引;也即,如果建(b,a)索引,用b查询可以用上索引,用a查询是用不上索引的,这个也符合复合索引字段的前置优先规则。

        3)如果我们的查询语句需要对a和b排序,那么建(a,b)或者(b,a)索引都可以用上索引,但是,这两种索引的效率取决于查询结果对应的a和b数据量。如果,查询出的文档结果集中,a的数量很多,b的数量很少,那么应该使用(b,a)索引,先找少的,再找多的,这样可以减少索引数据检索的范围。另外,查询语句中,a和b写的顺序不影响使用索引的效率,因为mongoDB会自动把查询语句优化,选择先查哪个,后查哪个。

1.2.2    索引方向

        查询语句若涉及到sort排序或者范围查询时,有可能需要指定索引的方向。

        1)sort排序。索引方向跟查询语句的sort排序顺序保持一致,这样,查的时候就可以直接按索引顺序取数据即可。否则,就用不了索引了,因此顺序反了,当然拿不到数据。

        2)范围查询。索引方向会影响范围查询的查询效率,索引数据是按照索引方向的顺序来排列的,我们需要让范围查询需要检索的数据尽可能少。例如,有1、2、3、4、......、10000的数据,范围查询条件是gt(10),如果索引方向是升序,那么只需要检索1~11,即可;如果索引方向是降序,那么需要索引10000~9,这个索引的数据量就大多了。

1.3    全文索引

        MongoDB提供了在文本字段上创建索引的功能,该索引还支持在集合中搜索某些字符串内容。 应注意,这些索引不存储诸如“该”,“一个”,“或”之类的停用词。 在文本索引中,单词仅用于存储根词。 我们可以使用以下查询在字段上创建文本索引:

        db.books.createIndex( { book_name: "text" } )

        文本全文索引是不区分大小写和不区分大小写的。文本索引建立起来的数据仅可进行模糊查询,适合因数据过大无法建立单键索引的词牌。

        一个查询只能指定最多一个$text表达式。不能使用hint()强制指定使用全文搜索。

        MongoDB中文全文索引建立方式与英文的简历几乎相同,是根据词(英文单词)的方式建立的。 如果一个值里面有多个值则需要按空格方式隔开,”张 王” 系统则认为是两个词。MongoDB的中文全文索引沒有想象中的强大。想要实现中文模糊搜素可以用elasticsearch或者Sphinx,或者lucene。

        此外,MongoDB还有全文索引相似度功能,$meta操作符:{score:{$meta:'textScore'}},写在查询条件后面可以返回返回结果的相似度,与sort一起使用,可以对相似度排序,实现搜索结果的关联程度排行。

        全文索引在工作还是经常使用的,比如博客文章的搜索,长文件的关键词搜索,这些都需要使用全文索引来进行。

1.4    内嵌文档索引

        对于文档嵌套的情况,也可以建立内嵌文档的索引,包括两种:

        1)第一种直接对内嵌文档建索引;

        2)第二种对内嵌文档里的Key建索引。

1.5    数据索引(多键索引)

        可以对数组直接建立索引,或者对内嵌文档内部的数组建立索引。

1.6    哈希索引

        这种类型的索引允许我们对内容执行基于哈希的分片。 在这种类型的索引中,键的值被散列。 由于这个原因,这些索引只能支持相等匹配过滤器查询,并且不能在基于范围的查询上工作。

        如果我们想在索引上运行范围查询,我们可能必须在同一个字段上创建多个索引,其中一个可以是常规索引,另一个可以是散列索引。 最后,Hashed索引将浮点字段截断为整数。 应尽可能避免对散列字段使用浮点。

2、索引属性

2.1    唯一索引

        这些索引可以通过规范使其成为唯一的。这样,当要求单个字段索引保持唯一时,它将拒绝该密钥的集合中已存在的值。 MongoDB中的任何索引都可以是唯一的。

        在复合索引中,索引值的唯一性通过与组成复合索引的键对应的值的组合来维持。

        在创建唯一索引的时候,明显感觉比创建单个索引慢很多,这是由于创建的时候需要检查其唯一性。而在所以创建之后发现已经存在两个索引,还有一个就是特殊的_id索引,就是一个唯一索引,只是该索引不能进行删除操作。所以在没有必要的情况下可以直接使用mongoDB的_id的值,如果是自己去实现的话在插入的时候会检查唯一性,会有性能影响(MongoDB的字段生成主键与ES的主键非常的类似,会有性能优化)。

        由于会检查唯一性,所以在创建索引的时候可能会失败,或者在创建好之后插入文档的时候也可能失败。在创建唯一索引之前可以使用聚合API查询一下是否存在重复的数据,若是数据非常重要则需要先备份和数据的预处理。否则可以使用dropDups可选项,将只保留一条重复的数据。如下:

    db.user.ensuerIndex({"username":1},{"unique":true , "dropDups":true});   # 不管怎么样,一定先备份数据

    还有一点需要注意的是,唯一索引的存储值不能超过1024KB,否则不会报错也不会受唯一约束。并且很难对问题进行排查。

2.2    稀疏索引

        稀疏索引仅包含具有索引字段的文档的条目,即使索引字段包含空值也是如此。索引会跳过缺少索引字段的任何文档。配合唯一索引使用,即可实现对存在的字段才使用唯一索引。

        a、间隙索引就是创建索引的索引列在某些文档上列不存在,导致索引存在间隙。 

        b、间隙索引在创建时应指定选项:{ sparse: true } 

        c、间隙索引列上可以指定唯一性约束

索引使用注意事项:

1)数据不超万条时,不需要使用索引。性能的提升并不明显,而大大增加了内存和硬盘的消耗。

2)查询数据超过表数据量30%时,不要使用索引字段查询。实际证明会比不使用索引更慢,因为它大量检索了索引表和我们原表。

3)数字索引,要比字符串索引快的多,在百万级甚至千万级数据量面前,使用数字索引是个明确的选择。

4)把你经常查询的数据做成一个内嵌数据(对象型的数据),然后集体进行索引;

5)线上环境建立索引,一定要加 {background: true},不然会卡死mongoDB进程。

你可能感兴趣的:(MongoDB索引)