在Mongodb中,主键(IDHACK)和次键(IXSCAN)的工作过程有什么不同?

在Mongodb中,主键(IDHACK)和次键(IXSCAN)的工作过程有什么不同?,mongodb,Mongodb,我做了一些测试来比较主键和辅键之间的find()性能 我在一个集合中插入了一百万个虚拟数据,一个对象看起来像贝娄 { "_id" : "1/1/1", "1stDocumentNum : "1/1/1" } 在插入所有虚拟数据之后,“\u id”字段已经有了一个索引(主键),Mongodb会自动分配给\u id字段,我在“1stDocumentNum”字段(辅助键)上创建了额外的索引 当我试着用两种不同的方法找到一个物体 查找具有“_id”字段的对象 查找具有“1stDocumentNum

我做了一些测试来比较主键和辅键之间的find()性能

我在一个集合中插入了一百万个虚拟数据,一个对象看起来像贝娄

{ "_id" : "1/1/1",
  "1stDocumentNum : "1/1/1"
}
在插入所有虚拟数据之后,“\u id”字段已经有了一个索引(主键),Mongodb会自动分配给\u id字段,我在“1stDocumentNum”字段(辅助键)上创建了额外的索引

当我试着用两种不同的方法找到一个物体

  • 查找具有“_id”字段的对象
  • 查找具有“1stDocumentNum”字段的对象
  • 结果如下所示

    使用Jmeter、Nginx、Php

  • 查找具有“_id”字段的对象 每秒吞吐量:10622
  • 在explain()中

  • 查找具有“1stDocumentNum”字段的对象 每秒吞吐量:8751
  • 在explain()中

    我想知道IDHACK和IXSCAN之间有什么区别,以及它们是如何工作的

    如果它们的工作方式完全相同,那么吞吐量不同的原因在于explain()中的阶段数

    有人能帮我理解吗?
    提前谢谢

    IDHACK表示您的查询已选择使用\u id字段索引。
    IXSCAN表示您的查询正在使用常规索引

    它只是关于查询路径优化

    默认情况下,“\u id”是具有哈希索引的字段,对于小数据集,哈希索引的工作速度较慢(哈希开销)。

    “1stDocumentNum”:1是一个二叉树索引,对于小数据集,它工作得更快

    这就是为什么在您的示例中1stDocumentNum索引比_id更快的原因


    尝试对100亿个文档运行相同的测试,您会发现散列索引的工作速度更快(通常,…取决于散列算法的分布)。

    IDHACK意味着您的查询已选择使用id字段索引。
    IXSCAN表示您的查询正在使用常规索引

    它只是关于查询路径优化

    默认情况下,“\u id”是具有哈希索引的字段,对于小数据集,哈希索引的工作速度较慢(哈希开销)。

    “1stDocumentNum”:1是一个二叉树索引,对于小数据集,它工作得更快

    这就是为什么在您的示例中1stDocumentNum索引比_id更快的原因


    尝试对100亿个文档运行相同的测试,您将看到散列索引工作得更快(通常,…取决于散列算法的分布)。

    IDHACK
    意味着查询使用了
    \u id
    索引,并绕过了查询计划阶段。“hack”是指绕过查询计划,因为
    \u id
    既是必需的,也是唯一的。默认情况下,
    \u id
    索引不会散列(并且MongoDB中散列的索引值仍然存储为B树)。没有足够的信息来理解问题中的比较结果,但它肯定与哈希索引无关。谢谢您的回复!虽然我需要更多地了解你的观点,但我还是接受了你的答案
    IDHACK
    表示查询使用了
    \u id
    索引并绕过了查询计划阶段。“hack”是指绕过查询计划,因为
    \u id
    既是必需的,也是唯一的。默认情况下,
    \u id
    索引不会散列(并且MongoDB中散列的索引值仍然存储为B树)。没有足够的信息来理解问题中的比较结果,但它肯定与哈希索引无关。谢谢您的回复!虽然我需要更多地了解你的观点,但我还是接受了你的答案!请使用
    explain(true)
    (所有候选计划)和特定版本的MongoDB服务器(x.y.z)编辑您的问题,以包含第二次查询的结果。您的测试是仅使用读取还是在同一集合上发生并发写入?
    IDHACK
    阶段意味着查询使用了
    \u id
    索引,并绕过了通常的查询。如果存在多个候选计划或频繁的计划重新评估,二次查询可能会有额外的开销,但在查询计划之外,两个索引的执行应该类似。完整的
    explain(true)
    output(aka)将提供更多关于不同查询路径是否正在做更多工作的信息。根据您的MongoDB服务器版本可能有所不同。谢谢您,Steenie!你给了我很多分数,我可以检查更多。非常感谢您的评论:)请编辑您的问题,将第二次查询的结果包含在
    explain(true)
    (所有候选计划)和您的特定版本的MongoDB服务器(x.y.z)中。您的测试是仅使用读取还是在同一集合上发生并发写入?
    IDHACK
    阶段意味着查询使用了
    \u id
    索引,并绕过了通常的查询。如果存在多个候选计划或频繁的计划重新评估,二次查询可能会有额外的开销,但在查询计划之外,两个索引的执行应该类似。完整的
    explain(true)
    output(aka)将提供更多关于不同查询路径是否正在做更多工作的信息。根据您的MongoDB服务器版本可能有所不同。谢谢您,Steenie!你给了我很多分数,我可以检查更多。我非常感谢你的评论:)
    "winningPlan" : {
    "stage" : "IDHACK"
    },
    
    "winningPlan" : {
    "stage" : "FETCH",
    "inputStage" : {
    "stage" : "IXSCAN",
    "keyPattern" : {
    "1stDocumentNum" : 1
    },