【发布时间】:2014-06-26 10:58:28
【问题描述】:
我正在尝试将 mongoDB 用于大量文档。只要数据更小并且适合内存,一切都可以正常工作,但是如果不适合,则读取/搜索性能很糟糕。对于 5 亿个文档集合,一个简单的索引查询(例如,对单个索引字段的正则表达式查询)运行近 2 小时。这很奇怪 - 集合大小约为。 300GB,从硬盘顺序读取应该不超过半小时。而且由于它使用索引,它应该更快(结果有大约 100k 个文档;集合中这个特定字段的不同值大约有 2M)。如果在(不同的)索引键上完成,单独的正则表达式匹配应该不超过几秒钟 - 匹配这些值的简单 python 脚本需要 6 秒。
据我所知,即使在使用此类索引处理查询(类似查询但没有结果)时,DBMS 也会以随机顺序访问磁盘。我使用了许多索引,它们都不能同时放入内存,所以这似乎是问题所在(它们使用 50-60GB,机器有 32GB 的 RAM)。因此,问题是:是否可以调整 DBMS I/O 方法以执行更智能的预读或操作排序?
或者也许我应该切换到 mongo 以外的东西?到目前为止,我已经看过 Lucene 和 Cassandra,我认为它们不符合我的需求。我的任务更详细:
我想使用DB根据对属性的一些要求从大量的小属性结构中选择文档。这些结构有时是嵌套的。我只需要检索它们的标识符以进行进一步处理,但所有属性/字段都用于搜索。我需要的操作是单个字段上条件的连接和替代条件,其中条件是:等于常量,正则表达式匹配(不是全文),加上子结构列表上的量词(列表上的所有子结构都有一个属性匹配正则表达式.. .,存在一个属性等于...的子结构,依此类推)。
典型的使用是并发只读操作;写入是不频繁的批量插入(独占 - 只写)。 500M 的集合是我的开发/测试数据,生产将使用多达 10G 的文档,10TB 的数据(这就是为什么像“购买更多 RAM”这样的任何建议都无济于事的原因)。
感谢您的帮助, 巴特
编辑:
.explain() 输出:
{
"cursor" : "BtreeCursor orth_1",
"isMultiKey" : false,
"n" : 107290,
"nscannedObjects" : 107290,
"nscanned" : 250202122,
"nscannedObjectsAllPlans" : 107290,
"nscannedAllPlans" : 250202122,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 2954078,
"nChunkSkips" : 0,
"millis" : 6193156,
"indexBounds" : {
"orth" : [
[
"",
{
}
],
[
/[A-Z].+ski/,
/[A-Z].+ski/
]
]
},
"server" : "bart:27017",
"filterSet" : false
}
日志条目:
2014-06-26T11:46:41.672+0200 [conn2] query nkjp_300m_noni.simple_nodes query: { query: { orth: /[A-Z].+ski/ }, $explain: true } planSummary: IXSCAN { orth: 1.0 } ntoreturn:0 ntoskip:0 nscanned:250202122 nscannedObjects:107290 keyUpdates:0 numYields:1016206 locks(micros) r:355736129 nreturned:1 reslen:1187 6193156ms
编辑2: 再次运行相同的查询,中间没有任何其他查询需要 130 秒。
【问题讨论】:
-
你应该提供一些调试信息。我认为
explain()输出将是理想的。另外,你确定 mongo 在这 2 个小时内做了什么吗?有没有我们可以使用的监控数据?日志条目?当时的系统资源如何(mem 使用情况、io 等)? -
我正在附加 .explain() 输出和日志条目。 Mongo 主要等待,CPU 使用率约为 1%,磁盘读取速度约为 1MB/s,内存几乎已满缓冲区/缓存。
-
你能告诉我们实际的查询吗?
-
这里是:
db.simple_nodes.find({'orth' : /[A-Z].+ski/}).explain() -
总是
/[A-Z].+ski/或/^[A-Z].+ski/或/[A-Z].+ski$/吗?
标签: mongodb