查询索引

  1. 索引存放在system.indexes集合中
  2. > show tables
  3. address
  4. data
  5. person
  6. system.indexes
  7. 默认会为所有的ID建上索引 而且无法删除
  8. > db.system.indexes.find()
  9. { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "mydb.person" }
  10. { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "mydb.address" }
  11. { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "mydb.data" }
  12. 单独查询一个集合的索引
  13. > db.person.getIndexes();
  14. [
  15.    {
  16.       "v" : 1,
  17.       "key" : {
  18.          "_id" : 1
  19.       },
  20.       "name" : "_id_",
  21.       "ns" : "mydb.person"
  22.    }
  23. ]
  24. >

创建索引

  1. > db.person.find();
  2. { "_id" : ObjectId("593011c8a92497992cdfac10"), "name" : "xhj", "age" : 30, "address" : DBRef("address", ObjectId("59314b07e693aae7a5eb72ab")) }
  3. { "_id" : ObjectId("59301270a92497992cdfac11"), "name" : "zzj", "age" : 2 }
  4. { "_id" : ObjectId("593015fda92497992cdfac12"), "name" : "my second child", "age" : "i do not know" }
  5. { "_id" : ObjectId("592ffd872108e8e79ea902b0"), "name" : "zjf", "age" : 30, "address" : { "province" : "河南省", "city" : "南阳市", "building" : "桐柏县" } }
  6. 1升序 -1降序
  7. > db.person.ensureIndex({age:1});
  8. {
  9.    "createdCollectionAutomatically" : false,
  10.    "numIndexesBefore" : 1,
  11.    "numIndexesAfter" : 2,
  12.    "ok" : 1
  13. }
  14. 可以在集合上创建索引
  15. > db.person.ensureIndex({address:1});
  16. {
  17.    "createdCollectionAutomatically" : false,
  18.    "numIndexesBefore" : 2,
  19.    "numIndexesAfter" : 3,
  20.    "ok" : 1
  21. }
  22. 复合索引
  23. > db.person.ensureIndex({name:1,address:1});
  24. {
  25.    "createdCollectionAutomatically" : false,
  26.    "numIndexesBefore" : 3,
  27.    "numIndexesAfter" : 4,
  28.    "ok" : 1
  29. }
  30. 唯一索引:
  31. > db.person.ensureIndex({name:1},{unique:true});
  32. {
  33.    "createdCollectionAutomatically" : false,
  34.    "numIndexesBefore" : 4,
  35.    "numIndexesAfter" : 5,
  36.    "ok" : 1
  37. }

复合索引使用前缀匹配,所以创建复合索引的时候,要把经常会有的部分查询作为前缀。

删除索引:

  1. 删除一个索引
  2. > db.person.dropIndex({name:1});
  3. { "nIndexesWas" : 5, "ok" : 1 }
  4. 删除所有索引
  5. > db.person.dropIndexes();
  6. {
  7.    "nIndexesWas" : 4,
  8.    "msg" : "non-_id indexes dropped for collection",
  9.    "ok" : 1
  10. }

查看执行计划的方法:explain ()

winningPlan是最终的执行计划 其中的indexBounds索引计划

  1. 在age上建立索引
  2. > db.person.ensureIndex({age:1});
  3. {
  4.    "createdCollectionAutomatically" : false,
  5.    "numIndexesBefore" : 1,
  6.    "numIndexesAfter" : 2,
  7.    "ok" : 1
  8. }
  9. > db.person.getIndexes();
  10. [
  11.    {
  12.       "v" : 1,
  13.       "key" : {
  14.          "_id" : 1
  15.       },
  16.       "name" : "_id_",
  17.       "ns" : "mydb.person"
  18.    },
  19.    {
  20.       "v" : 1,
  21.       "key" : {
  22.          "age" : 1
  23.       },
  24.       "name" : "age_1",
  25.       "ns" : "mydb.person"
  26.    }
  27. ]
  28. 查看执行计划 indexBounds可以看到走了age的索引
  29. > db.person.find({age:30}).explain();
  30. {
  31.    "queryPlanner" : {
  32.       "plannerVersion" : 1,
  33.       "namespace" : "mydb.person",
  34.       "indexFilterSet" : false,
  35.       "parsedQuery" : {
  36.          "age" : {
  37.             "$eq" : 30
  38.          }
  39.       },
  40.       "winningPlan" : {
  41.          "stage" : "FETCH",
  42.          "inputStage" : {
  43.             "stage" : "IXSCAN",
  44.             "keyPattern" : {
  45.                "age" : 1
  46.             },
  47.             "indexName" : "age_1",
  48.             "isMultiKey" : false,
  49.             "direction" : "forward",
  50.             "indexBounds" : {
  51.                "age" : [
  52.                   "[30.0, 30.0]"
  53.                ]
  54.             }
  55.          }
  56.       },
  57.       "rejectedPlans" : [ ]
  58.    },
  59.    "serverInfo" : {
  60.       "host" : "localhost.localdomain",
  61.       "port" : 27017,
  62.       "version" : "3.0.6",
  63.       "gitVersion" : "1ef45a23a4c5e3480ac919b28afcba3c615488f2"
  64.    },
  65.    "ok" : 1
  66. }
  67. 没有走索引的计划是这样的
  68. > db.person.find({name:'zjf'}).explain();
  69. {
  70.    "queryPlanner" : {
  71.       "plannerVersion" : 1,
  72.       "namespace" : "mydb.person",
  73.       "indexFilterSet" : false,
  74.       "parsedQuery" : {
  75.          "name" : {
  76.             "$eq" : "zjf"
  77.          }
  78.       },
  79.       "winningPlan" : {
  80.          "stage" : "COLLSCAN",
  81.          "filter" : {
  82.             "name" : {
  83.                "$eq" : "zjf"
  84.             }
  85.          },
  86.          "direction" : "forward"
  87.       },
  88.       "rejectedPlans" : [ ]
  89.    },
  90.    "serverInfo" : {
  91.       "host" : "localhost.localdomain",
  92.       "port" : 27017,
  93.       "version" : "3.0.6",
  94.       "gitVersion" : "1ef45a23a4c5e3480ac919b28afcba3c615488f2"
  95.    },
  96.    "ok" : 1
  97. }

强制索引 hint()方法:

  1. > db.person.ensureIndex({name:1,age:1});
  2. {
  3.    "createdCollectionAutomatically" : false,
  4.    "numIndexesBefore" : 3,
  5.    "numIndexesAfter" : 4,
  6.    "ok" : 1
  7. }
  8. > db.person.getIndexes();
  9. [
  10.    {
  11.       "v" : 1,
  12.       "key" : {
  13.          "_id" : 1
  14.       },
  15.       "name" : "_id_",
  16.       "ns" : "mydb.person"
  17.    },
  18.    {
  19.       "v" : 1,
  20.       "key" : {
  21.          "age" : 1
  22.       },
  23.       "name" : "age_1",
  24.       "ns" : "mydb.person"
  25.    },
  26.    {
  27.       "v" : 1,
  28.       "key" : {
  29.          "name" : 1
  30.       },
  31.       "name" : "name_1",
  32.       "ns" : "mydb.person"
  33.    },
  34.    {
  35.       "v" : 1,
  36.       "key" : {
  37.          "name" : 1,
  38.          "age" : 1
  39.       },
  40.       "name" : "name_1_age_1",
  41.       "ns" : "mydb.person"
  42.    }
  43. ]
  44. //如果不加hint 默认走age上的索引。
  45. > db.person.find({age:{$gt:0}}).explain();
  46. {
  47.    "queryPlanner" : {
  48.       "plannerVersion" : 1,
  49.       "namespace" : "mydb.person",
  50.       "indexFilterSet" : false,
  51.       "parsedQuery" : {
  52.          "age" : {
  53.             "$gt" : 0
  54.          }
  55.       },
  56.       "winningPlan" : {
  57.          "stage" : "FETCH",
  58.          "inputStage" : {
  59.             "stage" : "IXSCAN",
  60.             "keyPattern" : {
  61.                "age" : 1
  62.             },
  63.             "indexName" : "age_1",
  64.             "isMultiKey" : false,
  65.             "direction" : "forward",
  66.             "indexBounds" : {
  67.                "age" : [
  68.                   "(0.0, inf.0]"
  69.                ]
  70.             }
  71.          }
  72.       },
  73.       "rejectedPlans" : [ ]
  74.    },
  75.    "serverInfo" : {
  76.       "host" : "localhost.localdomain",
  77.       "port" : 27017,
  78.       "version" : "3.0.6",
  79.       "gitVersion" : "1ef45a23a4c5e3480ac919b28afcba3c615488f2"
  80.    },
  81.    "ok" : 1
  82. }
  83. //使用hint
  84. > db.person.find({age:{$gt:0}}).hint({name:1,age:1}).explain();
  85. {
  86.    "queryPlanner" : {
  87.       "plannerVersion" : 1,
  88.       "namespace" : "mydb.person",
  89.       "indexFilterSet" : false,
  90.       "parsedQuery" : {
  91.          "age" : {
  92.             "$gt" : 0
  93.          }
  94.       },
  95.       "winningPlan" : {
  96.          "stage" : "KEEP_MUTATIONS",
  97.          "inputStage" : {
  98.             "stage" : "FETCH",
  99.             "filter" : {
  100.                "age" : {
  101.                   "$gt" : 0
  102.                }
  103.             },
  104.             "inputStage" : {
  105.                "stage" : "IXSCAN",
  106.                "keyPattern" : {
  107.                   "name" : 1,
  108.                   "age" : 1
  109.                },
  110.                "indexName" : "name_1_age_1",
  111.                "isMultiKey" : false,
  112.                "direction" : "forward",
  113.                "indexBounds" : {
  114.                   "name" : [
  115.                      "[MinKey, MaxKey]"
  116.                   ],
  117.                   "age" : [
  118.                      "[MinKey, MaxKey]"
  119.                   ]
  120.                }
  121.             }
  122.          }
  123.       },
  124.       "rejectedPlans" : [ ]
  125.    },
  126.    "serverInfo" : {
  127.       "host" : "localhost.localdomain",
  128.       "port" : 27017,
  129.       "version" : "3.0.6",
  130.       "gitVersion" : "1ef45a23a4c5e3480ac919b28afcba3c615488f2"
  131.    },
  132.    "ok" : 1
  133. }

查看执行情况:

  1. db.person.find({name:'zjf'}).explain('executionStats');
  2. {
  3.    "queryPlanner" : {
  4.       "plannerVersion" : 1,
  5.       "namespace" : "mydb.person",
  6.       "indexFilterSet" : false,
  7.       "parsedQuery" : {
  8.          "name" : {
  9.             "$eq" : "zjf"
  10.          }
  11.       },
  12.       "winningPlan" : {
  13.          "stage" : "FETCH",
  14.          "inputStage" : {
  15.             "stage" : "IXSCAN",
  16.             "keyPattern" : {
  17.                "name" : 1
  18.             },
  19.             "indexName" : "name_1",
  20.             "isMultiKey" : false,
  21.             "direction" : "forward",
  22.             "indexBounds" : {
  23.                "name" : [
  24.                   "[\"zjf\", \"zjf\"]"
  25.                ]
  26.             }
  27.          }
  28.       },
  29.       "rejectedPlans" : [
  30.          {
  31.             "stage" : "FETCH",
  32.             "inputStage" : {
  33.                "stage" : "IXSCAN",
  34.                "keyPattern" : {
  35.                   "name" : 1,
  36.                   "age" : 1
  37.                },
  38.                "indexName" : "name_1_age_1",
  39.                "isMultiKey" : false,
  40.                "direction" : "forward",
  41.                "indexBounds" : {
  42.                   "name" : [
  43.                      "[\"zjf\", \"zjf\"]"
  44.                   ],
  45.                   "age" : [
  46.                      "[MinKey, MaxKey]"
  47.                   ]
  48.                }
  49.             }
  50.          }
  51.       ]
  52.    },
  53.    "executionStats" : {
  54.       "executionSuccess" : true,
  55.       "nReturned" : 1,
  56.       "executionTimeMillis" : 0,
  57.       "totalKeysExamined" : 1,
  58.       "totalDocsExamined" : 1,
  59.       "executionStages" : {
  60.          "stage" : "FETCH",
  61.          "nReturned" : 1,
  62.          "executionTimeMillisEstimate" : 0,
  63.          "works" : 3,
  64.          "advanced" : 1,
  65.          "needTime" : 0,
  66.          "needFetch" : 0,
  67.          "saveState" : 0,
  68.          "restoreState" : 0,
  69.          "isEOF" : 1,
  70.          "invalidates" : 0,
  71.          "docsExamined" : 1,
  72.          "alreadyHasObj" : 0,
  73.          "inputStage" : {
  74.             "stage" : "IXSCAN",
  75.             "nReturned" : 1,
  76.             "executionTimeMillisEstimate" : 0,
  77.             "works" : 2,
  78.             "advanced" : 1,
  79.             "needTime" : 0,
  80.             "needFetch" : 0,
  81.             "saveState" : 0,
  82.             "restoreState" : 0,
  83.             "isEOF" : 1,
  84.             "invalidates" : 0,
  85.             "keyPattern" : {
  86.                "name" : 1
  87.             },
  88.             "indexName" : "name_1",
  89.             "isMultiKey" : false,
  90.             "direction" : "forward",
  91.             "indexBounds" : {
  92.                "name" : [
  93.                   "[\"zjf\", \"zjf\"]"
  94.                ]
  95.             },
  96.             "keysExamined" : 1,
  97.             "dupsTested" : 0,
  98.             "dupsDropped" : 0,
  99.             "seenInvalidated" : 0,
  100.             "matchTested" : 0
  101.          }
  102.       }
  103.    },
  104.    "serverInfo" : {
  105.       "host" : "localhost.localdomain",
  106.       "port" : 27017,
  107.       "version" : "3.0.6",
  108.       "gitVersion" : "1ef45a23a4c5e3480ac919b28afcba3c615488f2"
  109.    },
  110.    "ok" : 1
  111. }

Mongodb的索引使用的是B-树。

hash索引:

散列索引使用索引字段的值的散列值来维护条目。

散列索引的重要特征是hash后的键值是均匀分布的,索引最适合的是做分片键。

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

MongoDB支持任何单个字段的散列索引。 散列函数折叠嵌入文档并计算整个值的散列值,但不支持多键(即数组)索引。

您不得创建具有散列索引字段或在散列索引上指定唯一约束的复合索引; 但是,您可以在同一字段上创建散列索引和升序/降序(即非散列)索引:MongoDB将使用范围查询的标量索引。

警告

MongoDB散列索引在浮动之前将浮点数截断为64位整数。 例如,散列索引将为保持值为2.3,2.2和2.9的字段存储相同的值。 为了防止冲突,不要使用不能可靠地转换为64位整数(然后返回到浮点)的浮点数的散列索引。 MongoDB散列索引不支持大于253的浮点值。

散列索引支持等值查询。

索引大小

为了达到更快的处理效果,请确保您的索引能完整地和内存相适应,这样可以避免从磁盘上读取索引。

可以使用帮助函数 db.collection.totalIndexSize() 来检查索引的大小,返回的数值单位是字节:

> db.collection.totalIndexSize()

4294976499

上述例子展示了一个几乎4.3GB的索引。为了确保索引与内存相适应,您不仅需要有那么多足够可用的内存用于索引,还要有足够的内存用于剩下的 working set 。

稀疏索引

稀疏索引(或者称间隙索引)就是只包含有索引字段的文档的条目,跳过索引键不存在的文档

创建间隙索引示例:

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

这个示例,哪些不包含xmpp_id的键(列)的文档将不会被索引

间隙索引不会被使用到的情形

如果一个间隙索引会导致查询或者排序操作得到一个不完整结果集的时候,MongoDB将不会使用这个索引,hint提示除外

如果集合中有大量的数据都不包含该键值,那么应该使用稀疏索引。

覆盖索引:

整个结果集都是从索引中获取。

慢查询分析:

慢查询分析流程:

1.用慢查询日志(system.profile)找到超过200ms的语句

2.然后再通过.explain()解析影响行数,分析为什么超过200ms

3.决定是不是需要添加索引

开启慢查询:

db.setProfilingLevel(1,200)

参数:

  • 0:关闭,不收集任何数据。
  • 1:收集慢查询数据,默认是100毫秒。
  • 2:收集所有数据

查看结果:

db.system.profile.find()

注意:索引基本上可以说是常驻在内存中的,索引如果数据量达到亿级,索引的 数量越少越好,因为会占据大量的内存。网上的说法,100万条索引约占50M内存。如果一个亿,那么将占据5g内存。

以下来自网络:

不要被FindOne({_id:xxx}).Items[3].ItemType这优雅的代码欺骗,这是非常慢的,他几乎谋杀你所有的流量。

无论后面是什么 FindOne({_id:xxx})总是返回给你完整的Value,我们的100条道具,少说也有6~8K.

这样的查询流量已经很大了,如果你采用MongoDB方案一设计,你的单个Value是包含一个用户的所有数据的,他会更大。

如果查询客户端和数据库服务器不在同一个机房,流量将成为一个很大的瓶颈。

我们应该使用的查询函数是FindOne({_id:xxx},filter),filter里面就是设置返回的过滤条件,这会在发送给你以前就过滤掉

比如FindOne({_id:xxx},{Items:{"$slice":[3,1]}}),这和上面那条优雅的代码是完成同样功能,但是他消耗很少的流量

这和问题二相对的,不要暴力的FindOne,也尽量不要暴力的Update一整个节点。虽然MangoDB的性能挺暴力的,IO性能极限约等于MongoDB性能,暴力的Update就会在占用流量的同时迎接IO的性能极限。

除了创建节点时的Insert或者Save之外,所有的Update都应该使用修改器精细修改.

比如Update({_id:xxx},{$set:{"Items.3.Item.Health":38}});//修改第三把武器的健康值

Mongodb索引和执行计划 hint 慢查询的更多相关文章

  1. python/MySQL(索引、执行计划、BDA、分页)

    ---恢复内容开始--- python/MySQL(索引.执行计划.BDA.分页) MySQL索引: 所谓索引的就是具有(约束和加速查找的一种方式)   创建索引的缺点是对数据进行(修改.更新.删除) ...

  2. MySQL for OPS 03:索引和执行计划

    写在前面的话 啥是索引?以一本书为例,如果想要找到某一指定章节的某一小节,书薄还好,如果书厚,可能就会找的头皮发麻.于是便出现了目录,让用户更容易查找到自己所需要的东西.索引就类似一张表的目录.其存在 ...

  3. oracle -- 查询执行计划,判读查询语句优劣

    以oracle的scott账户:找到员工表中薪水大于本部门平均薪水的员工为例 多表查询方式: select e.empno, e.ename, e.sal, d.avgsal from emp e, ...

  4. 第九课——MySQL优化之索引和执行计划

    一.创建索引需要关注什么? 1.关注基数列唯一键的数量: 比如性别,该列只有男女之分,所以性别列基数是2: 2.关注选择性列唯一键与行数的比值,这个比值范围在0~1之前,值越小越好: 其实,选择性列唯 ...

  5. SQL Server索引的执行计划

    如何知道索引有问题,最直接的方法就是查看执行计划.通过执行计划,可以回答表上的索引是否被使用的问题. (1)包含索引:避免书签查找 常见的索引方面的性能问题就是书签查找,书签查找分为RID查找和键值查 ...

  6. mongodb索引--1亿条记录的查询从55.7秒到毫秒级别<补充版>

    从头开始,验证mongodb的索引的好处.(window7环境下) 下载mongodb服务器,并解压到d盘,并使用以下命令启动 mongod --dbpath D:\mongodb\data mong ...

  7. mysql的索引和执行计划

    一.mysql的索引 索引是帮助mysql高效获取数据的数据结构.本质:索引是数据结构 1:索引分类 普通索引:一个索引只包含单个列,一个表可以有多个单列索引. 唯一索引:索引列的值必须唯一 ,但允许 ...

  8. Solr-DIH建立索引并执行简单初步的查询

    我们将solr的安装目录设置为$SOLR_INSTALL,   ./solr start,不使用任何原有的examples来进行,启动完成后,不存在任何的core,提示No cores availab ...

  9. 第二百八十八节,MySQL数据库-索引、limit分页、执行计划、慢日志查询

    MySQL数据库-索引.limit分页.执行计划.慢日志查询 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获 ...

随机推荐

  1. 转SQLSERVER 会不会自动加锁

    [SQL]提升查询效率与避免LOCK发生nolock: 可能把没有提交事务的数据也显示出来,可能会产生脏读readpast: 会把被锁住的行不显示出来 所有Select加 With (NoLock)解 ...

  2. VS快捷键操作

    1.窗口快捷键记忆诀窍: 凡跟窗口挂上钩的快捷键必有一个W(Windows):Ctrl+W,W: 浏览器窗口 (浏览橱窗用有道的翻译是window shopping) Ctrl+W,S: 解决方案管理 ...

  3. 利用WatchService监控C盘根目录下的文件情况

    public static void main(String[] args) throws IOException, InterruptedException { WatchService watch ...

  4. 二 MyBatis 从入门到进阶 2 Maven 入门

    1 Maven 的使用 1.1 本地仓库与中央仓库 本地仓库:Window \ Preferences \ Maven \ User Settings \ Local Repository 中央仓库: ...

  5. ubuntu查看目录大小

    du -h --max-depth=1 该命令会查看目录下的所有子目录大小,以及目录总共占用磁盘空间

  6. "在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配" 问题总结

    最近C#连接ODBC数据源时,总是提示"[Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配",百度查询之后才知道原来是 ...

  7. Kali Linux 2019.2使用华为源

    一.将默认的配置源注释掉 root@zinuo:~# vim /etc/apt/sources.list 注释: #deb http://http.kali.org/kali kali-rolling ...

  8. 论文阅读 | Generating Fluent Adversarial Examples for Natural Languages

    Generating Fluent Adversarial Examples for Natural Languages   ACL 2019 为自然语言生成流畅的对抗样本 摘要 有效地构建自然语言处 ...

  9. BUUOJ misc 金三胖

    可以看到是有三帧的内容有flag的 直接 convert aaa.gif .png 逐帧分解,得到: flag{he11ohongke} (kali真好用呀)

  10. [转帖]全方位掌握OpenStack技术知识

    全方位掌握OpenStack技术知识 http://www.itpub.net/2019/06/17/2206/ 架构师技术联盟的文章 相当好呢. 大家好,我是小枣君.最近几年,OpenStack这个 ...