MongoDB 查询 lte 比 gte 快
Posted
技术标签:
【中文标题】MongoDB 查询 lte 比 gte 快【英文标题】:MongoDB query faster lte than 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 毫秒。
谁能找出问题所在或帮我找到它?
【问题讨论】:
【参考方案1】:您正在尝试执行的操作存在一些问题:
$or
查询使用不同的索引
要使$or
查询能够使用索引,$or
查询的所有 项必须具有索引。否则,查询将是集合扫描。这在https://docs.mongodb.com/manual/reference/operator/query/or/#or-clauses-and-indexes中有描述
集合中的索引过多
集合中的索引过多会以多种方式影响性能,例如,插入性能会受到影响,因为您将一个插入操作转换为多个(即为集合插入一个,为您的每个索引添加一个额外的插入)收藏)。太多看起来相似的索引也对查询计划器不利,因为它需要从许多相似的索引中选择一个索引,而关于哪个索引性能更高的信息很少。
检查mongo
shell 中的explain()
输出
mongo
shell 中的explain()
输出是发现查询将使用哪个索引的最佳工具。通常,您希望避免任何COLLSCAN
阶段(这意味着收集扫描)和SORT_KEY_GENERATOR
阶段(这意味着 MongoDB 正在使用限制为 32MB 的内存排序,请参阅https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/)。详情请见Explain Results。
您可能想查看这些有关索引和查询性能的相关页面:
Analyze Query Performance Use Indexes to Sort Query Results Indexing Strategies话虽如此,我使用您的示例快速检查了mongo
shell (MongoDB 3.2.8)。您可以尝试在您的集合中添加这两个索引:
blockNumber:1,transactionIndex:1,from:1
blockNumber:1,transactionIndex:1,to:1
并且删除集合中的所有其他索引。这两个索引应该能够在您的两个示例查询中使用。
【讨论】:
使用这些索引效果更差。我认为问题在于某些查询返回大量文档并且排序需要时间。我真的不明白解释如何帮助我,它看起来像汇编语言。如果结果是 67000,那么排序很慢。我曾经使用 Cassandra,您可以在其中指定表的默认顺序,这在您需要始终以特定顺序检索结果时非常有用。看起来 Mongo 缺少我需要的这个功能。以上是关于MongoDB 查询 lte 比 gte 快的主要内容,如果未能解决你的问题,请参考以下文章
$match 与 $gte 和 $lte 不适用于 mongodb 中的数组? [复制]
$match 与 $gte 和 $lte 不适用于 mongodb 中的数组? [复制]
[转]mongodb 查询条件:关系运算符"$lt", "$lte", "$gt", "$gte", "$ne
MongoDB $关键字 关系比较符号 $lt $lte $gt $gte $ne
$gte 和 $lte 在 Mongoose/MongoDB 中没有按预期工作
包含greaterThanEqual(gte)或lessThanEqual(lte)的Squeryl查询给出错误/无结果