MongoDB查询速度比gte快

时间:2016-07-14 17:26:36

标签: mongodb performance mongoose mongodb-query

这个问题让我发疯了。我有一个集合:

var ethTransactionSchema = new mongoose.Schema({
    blockNumber: Number,
    blockHash: String,
    hash: String,
    transactionIndex: Number,
    from: String,
    to: String,
    value: String
});
ethTransactionSchema.index({ hash: 1 }, { unique: true });
ethTransactionSchema.index({ from: 1 });
ethTransactionSchema.index({ to: 1 });
ethTransactionSchema.index({ blockNumber: 1, transactionIndex: 1 });

ethTransactionSchema.index({ from: 1, to: 1, blockNumber: 1, transactionIndex: 1 });
ethTransactionSchema.index({ from: 1, blockNumber: 1, transactionIndex: 1});

ethTransactionSchema.index({ to: 1, blockNumber: 1, transactionIndex: 1 });
ethTransactionSchema.index({ to: 1, blockNumber: 1 });

ethTransactionSchema.index({ from: 1, blockNumber: 1 });
ethTransactionSchema.index({ from: 1, to: 1, blockNumber: 1 });
ethTransactionSchema.index({ blockNumber: 1 });
ethTransactionSchema.index({ transactionIndex: 1 });

ethTransactionSchema.index({ blockNumber: -1 });
ethTransactionSchema.index({ to: 1, blockNumber: -1 });
ethTransactionSchema.index({ from: 1, blockNumber: -1 });
ethTransactionSchema.index({ from: 1, to: 1, blockNumber: -1 });

ethTransactionSchema.index({ from: 1, to: 1, blockNumber: -1, transactionIndex: -1 });
ethTransactionSchema.index({ from: 1, blockNumber: -1, transactionIndex: -1 });
ethTransactionSchema.index({ to: 1, blockNumber: -1, transactionIndex: -1 });

执行此查询时:

  find({"$and":[ {"$or": [ {"from":"0x120a270bbc009644e35f0bb6ab13f95b8199c4ad"},
                      {"to":"0x120a270bbc009644e35f0bb6ab13f95b8199c4ad"}
                    ]},
            {"blockNumber":{"$gte":1289597}}
          ]
  }).sort({ blockNumber: -1, transactionIndex: -1 })

使用lte:

的同一查询需要3到6倍
  find({"$and":[ {"$or": [ {"from":"0x120a270bbc009644e35f0bb6ab13f95b8199c4ad"},
                      {"to":"0x120a270bbc009644e35f0bb6ab13f95b8199c4ad"}
                    ]},
            {"blockNumber":{"$lte":1289597}}
          ]
  }).sort({ blockNumber: -1, transactionIndex: -1 })

你可以看到我尝试了很多索引组合只是为了测试我是否可以使用frute force解决问题,但我可能会遗漏一些东西。我出于这个原因即将放弃MongoDB。 快速查询需要56毫秒,缓慢的167毫秒平均值。

有人可以找出问题的原因或帮助我找到它吗?

1 个答案:

答案 0 :(得分:4)

您尝试做的事情存在一些问题:

  1. $or查询使用不同的索引

    要使$or个查询能够使用索引,$or查询的所有条款必须具有索引。否则,查询将是集合扫描。这在https://docs.mongodb.com/manual/reference/operator/query/or/#or-clauses-and-indexes

  2. 中有所描述
  3. 集合中的索引太多

    集合中包含太多索引会以多种方式影响性能,例如,插入性能会受到影响,因为您将一个插入操作转换为多个(即集合的一个插入,以及您的每个索引的一个额外插入)采集)。太多看起来相似的索引对查询计划程序也是有害的,因为它需要从许多类似的索引中选择一个索引,而关于哪个索引的性能信息最少。

  4. 检查explain() shell中的mongo输出

    explain() shell中的mongo输出是发现查询将使用哪个索引的最佳工具。通常,您希望避免任何COLLSCAN阶段(这意味着集合扫描)和SORT_KEY_GENERATOR阶段(这意味着MongoDB使用的内存排序限制为32MB,请参阅{{3} })。有关详细信息,请参阅https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/

  5. 您可能需要查看有关索引和查询效果的相关页面:

    话虽如此,我使用您的示例快速检查了mongo shell(MongoDB 3.2.8)。您可以尝试在集合中添加这两个索引:

    {blockNumber:1,transactionIndex:1,from:1}
    {blockNumber:1,transactionIndex:1,to:1}
    

    删除集合中的所有其他索引。这两个索引应该可以在你的两个示例查询中使用。