【问题标题】:MongoDB query faster lte than gteMongoDB 查询 lte 比 gte 快
【发布时间】:2016-11-17 17:53:02
【问题描述】:

这个问题快把我逼疯了。我有一个收藏:

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 })

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

谁能找出问题所在或帮我找到它?

【问题讨论】:

    标签: mongodb performance mongoose mongodb-query


    【解决方案1】:

    您正在尝试执行的操作存在一些问题:

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

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

    2. 集合中的索引过多

      集合中的索引过多会以多种方式影响性能,例如,插入性能会受到影响,因为您将一个插入操作转换为多个(即为集合插入一个,为您的每个索引添加一个额外的插入)收藏)。太多看起来相似的索引也对查询计划器不利,因为它需要从许多相似的索引中选择一个索引,而关于哪个索引性能更高的信息很少。

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

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

    您可能想查看这些有关索引和查询性能的相关页面:

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

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

    并且删除集合中的所有其他索引。这两个索引应该能够在您的两个示例查询中使用。

    【讨论】:

    • 使用这些索引效果更差。我认为问题在于某些查询返回大量文档并且排序需要时间。我真的不明白解释如何帮助我,它看起来像汇编语言。如果结果是 67000,那么排序很慢。我曾经使用 Cassandra,您可以在其中指定表的默认顺序,这在您需要始终以特定顺序检索结果时非常有用。看起来 Mongo 缺少我需要的这个功能。
    猜你喜欢
    • 2016-12-23
    • 2013-06-07
    • 2021-09-17
    • 2015-12-27
    • 1970-01-01
    • 2017-08-17
    • 2022-12-05
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多