查询索引

  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. react中component存在性能问题

    Component存在的问题? 1). 父组件重新render(), 当前组件也会重新执行render(), 即使没有任何变化 2). 当前组件setState(), 重新执行render(), 即使 ...

  2. Python面试简介及并行并发

    今天的分享内容大体如下: 一. 面试 1. 什么是面试 2. 优秀的面试 二. Python综述 1. Python设计哲学及版本变迁 2. Python发展现状及其他语言使用场景 3. GIL 4. ...

  3. 人工智能01 刺激响应agent

    刺激响应agent 不具有内部状态而仅对其所处环境的即刻刺激有所反应的机器称为刺激响应(SR)agent 感知和动作 一机器人可以感知出周围8个单元是否空缺.这些传感器输入用二进制变量s1,s2 ,s ...

  4. CISCO路由器WAN口动态ISP配置

        Building configuration... version 15.0 service timestamps debug datetime msec service timestamps ...

  5. 【VS开发】进程线程及堆栈关系的总结

    进程线程及堆栈关系的总结 突然想到进程的栈和线程的栈,就顺便说一下,线程的栈被自动分配到进程的内存空间中 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性. ...

  6. SolidWorks学习笔记1

    鼠标 修改缩放方向 点击工具->选项->视图,点击第一条,翻转鼠标滚轮缩放方向. 平移:Ctrl+ 中键 或者右键空白处 菜单选择平移 缩放:Shift+中键 或者右键空白处 菜单选择放大 ...

  7. sqlalchemy的常用字段

    #encoding: utf-8 from sqlalchemy import create_engine,Column,Integer,String,\ Float,Boolean,DECIMAL, ...

  8. Linux 概念与快捷方式

    概念 何为shell Shell 是指"提供给使用者使用界面"的软件(命令解析器),类似于 DOS 下的 command(命令行)和后来的 cmd.exe .普通意义上的 Shel ...

  9. 从零开始,SpreadJS新人学习笔记【第3周】

    表单&函数 阔别多日, SpreadJS新人学习笔记,本周起正式回归!(在断更的这一个月中,我为大家先后录制了14期SpreadJS产品入门系列学习视频,希望帮助那些正在学习和使用 Sprea ...

  10. Spring 最常用的 7 大类注解,史上最强整理!

    随着技术的更新迭代,Java5.0开始支持注解.而作为java中的领军框架spring,自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用注解来控制spring框架. 而spring的的注解那 ...