- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我在配备 64 GB RAM 的笔记本电脑上运行 Community MongoDB 3.4.9。我收藏了超过 12 万份文件。每个文档至少有 Int64 类型的 from
和 to
字段。 from
-to
是唯一的范围。没有范围重叠的文档。集合上有索引如下:
{
"v" : NumberInt(1),
"unique" : true,
"key" : {
"from" : NumberInt(1),
"to" : NumberInt(1)
},
"name" : "range",
"ns" : "db.location",
"background" : true
}
服务器/数据库空闲。没有客户。我一遍又一遍地运行下面的查询,我得到大约 21 秒的恒定执行时间。
db.location.find({from:{$lte:NumberLong(3682093364)},to:{$gte:NumberLong(3682093364)}}).limit(1)
和
条件的反转不会对执行时间产生影响。 explain
命令显示以下内容。
{
"queryPlanner" : {
"plannerVersion" : 1.0,
"namespace" : "db.location",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"from" : {
"$lte" : NumberLong(3682093364)
}
},
{
"to" : {
"$gte" : NumberLong(3682093364)
}
}
]
},
"winningPlan" : {
"stage" : "LIMIT",
"limitAmount" : 1.0,
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"from" : 1.0,
"to" : 1.0
},
"indexName" : "range",
"isMultiKey" : false,
"multiKeyPaths" : {
"from" : [
],
"to" : [
]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1.0,
"direction" : "forward",
"indexBounds" : {
"from" : [
"[-inf.0, 3682093364]"
],
"to" : [
"[3682093364, inf.0]"
]
}
}
}
},
"rejectedPlans" : [
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1.0,
"executionTimeMillis" : 21526.0,
"totalKeysExamined" : 12284007.0,
"totalDocsExamined" : 1.0,
"executionStages" : {
"stage" : "LIMIT",
"nReturned" : 1.0,
"executionTimeMillisEstimate" : 20945.0,
"works" : 12284008.0,
"advanced" : 1.0,
"needTime" : 12284006.0,
"needYield" : 0.0,
"saveState" : 96299.0,
"restoreState" : 96299.0,
"isEOF" : 1.0,
"invalidates" : 0.0,
"limitAmount" : 1.0,
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 1.0,
"executionTimeMillisEstimate" : 20714.0,
"works" : 12284007.0,
"advanced" : 1.0,
"needTime" : 12284006.0,
"needYield" : 0.0,
"saveState" : 96299.0,
"restoreState" : 96299.0,
"isEOF" : 0.0,
"invalidates" : 0.0,
"docsExamined" : 1.0,
"alreadyHasObj" : 0.0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1.0,
"executionTimeMillisEstimate" : 20357.0,
"works" : 12284007.0,
"advanced" : 1.0,
"needTime" : 12284006.0,
"needYield" : 0.0,
"saveState" : 96299.0,
"restoreState" : 96299.0,
"isEOF" : 0.0,
"invalidates" : 0.0,
"keyPattern" : {
"from" : 1.0,
"to" : 1.0
},
"indexName" : "range",
"isMultiKey" : false,
"multiKeyPaths" : {
"from" : [
],
"to" : [
]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1.0,
"direction" : "forward",
"indexBounds" : {
"from" : [
"[-inf.0, 3682093364]"
],
"to" : [
"[3682093364, inf.0]"
]
},
"keysExamined" : 12284007.0,
"seeks" : 12284007.0,
"dupsTested" : 0.0,
"dupsDropped" : 0.0,
"seenInvalidated" : 0.0
}
}
},
"allPlansExecution" : [
]
},
"serverInfo" : {
"host" : "LAPTOP-Q96TVSN8",
"port" : 27017.0,
"version" : "3.4.9",
"gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
},
"ok" : 1.0
}
提供一个提示
并没有什么不同。 explain
似乎表明已经使用了正确的(且唯一的)索引,但大部分执行时间(20 秒)都花在了 IXSCAN
中。 MongoDB 日志显示扫描了许多索引项,但只有一个文档被触及并返回。考虑到数据库上的并发操作为零,它还显示了疯狂数量的锁和产量。底层引擎是 SSD 磁盘上的 wiredTiger
。 MongoDB RAM 使用量为 7 GB。
2017-10-10T10:06:14.456+0200 I COMMAND [conn33] command db.location appName: "MongoDB Shell" command: explain { explain: { find: "location", filter: { from: { $lte: 3682093364 }, to: { $gte: 3682093364 } }, limit: 1.0, singleBatch: false }, verbosity: "allPlansExecution" } numYields:96299 reslen:1944 locks:{ Global: { acquireCount: { r: 192600 } }, Database: { acquireCount: { r: 96300 } }, Collection: { acquireCount: { r: 96300 } } } protocol:op_command 21526ms
考虑到我的范围从不重叠,是否有更好的方法来构建文档以便查找更快?有什么明显的地方我做错了吗?
更新:
当我删除索引时,使用 COLLSCAN
并在一致的 8-9 秒内找到文档。
最佳答案
我讨厌回答自己的问题,但我还是很高兴找到解决方案。
尽管创建这样一个复合索引是有意义的,但考虑到非重叠范围的具体情况,事实证明搜索范围太广了。输入数字越大,查找结果所需的时间越长,因为会发现越来越多的索引条目满足 from <= number
搜索范围内的最后一个结果实际上就是我们要查找的结果(索引从左到右扫描)。
解决方案是将索引修改为 { from: -1 }
或 { to: 1 }
.在这种情况下,复合索引实际上不是必需的,因为范围没有重叠,索引找到的第一个文档就是返回的文档。正如预期的那样,这现在快如闪电。
你生活和学习......
关于mongodb - 带有索引的 MongoDB $lte + $gte 查询慢得令人无法接受,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46661709/
很抱歉新手的问题,但是: 我最近才发现“=”运算符不只是处理对象/等等。值(value),也是引用。这很酷,但我认为这对变量来说是不一样的,它不会在存储整数或 float 的变量之间创建引用。后来我觉
我是一名优秀的程序员,十分优秀!