我有一个拥有10亿条记录的MongoDB集合。它是电信SMSC节点的最后15天日志,它基本上保持通过SMSC发送的所有短信的传送状态。我正在努力根据DateTime过滤器选择数据。它真的很慢。当我尝试从此集合中删除大量记录以删除超过两周的日志时,它也非常慢。删除查询字面上永远不会结束。说到这一切,我正在使用的电脑是非常常见的台式机戴尔PC,它配备了带有4GB内存的Core i7处理器。有什么建议吗?
答案 0 :(得分:3)
这些是关键:
创建支持查询的索引
限制查询结果的数量以减少网络需求
使用预测仅返回必要的数据
使用$ hint选择特定索引
使用增量运算符执行Operations Server端
您可以在https://docs.mongodb.org/manual/tutorial/optimize-query-performance-with-indexes-and-projections/
中找到解释答案 1 :(得分:3)
您可以发布文档结构吗?
我怀疑有两件事。首先,对于10亿条记录,我认为你严重缺乏内存。如果你不把你的工作集保留在内存中,MongoDB的性能会下降。至少,这包括您的索引。但是为了获得良好的性能,您还应该包括足够的工作集(即数据库例行访问的文档数量,例如,如果您的查询通常在任何给定时间对一百万个文档进行处理)。即使是10亿条记录的微小索引(如_id字段的主索引)也需要4GB以上。
其次,你确定你有合适的索引吗?并且您的查询正在使用您的索引?您似乎需要时间戳字段上的索引,以及您可能查询的任何字段(例如,如果您的删除查询还包括除时间戳之外的其他搜索字词)。
我建议的第一步是获取索引的大小。您可以通过键入db.collection.stats().indexSizes
在mongo shell中执行此操作。您需要的最小RAM是您的索引大小+工作集的一些金额。
一旦有足够的RAM,接下来确保您的查询正在使用您的索引。你可以使用Mongo的explain()功能查看任何查询的查询计划,你可以看出你是否真的在点击索引,或者Mongo是否绕过它们并进行完整的文档搜索。
如果你已经定义了适当的索引,有足够的内存来保存你的工作集(索引+你经常访问的文档集),并确保你的查询正在使用你的索引,那么,移动它可能是合适的其他策略,如分片。但考虑到你目前的计算机统计数据(特别是4GB内存),我怀疑你只需要完成上面列出的第一步即可。[/ p>
答案 2 :(得分:1)
以下是该集合的样本数据。
示例数据:
{ “_id”:ObjectId(“56eacd643f8621ca653d5bf3”), “节点”:“torsmsc11”, “MESSAGE_ID”:“1264F954”, “CDR_TYPE”:“初始MO”, “SUB_TIME”:“2016-03-17 08:59:50”, “DEL_TIME”:“2016-03-17 08:59:50”, “OA_ADDR”:NumberLong(“16477392921”), “PRE_TRANS_OA”:NumberLong(“16477392921”), “DA_ADDR”:NumberLong(“16472202975”), “PRE_TRANS_DA”:NumberLong(“16472202975”), “ORIG_LOCN”:NumberLong(“161350003000”), “ORIG_IDNT”:NumberLong(“302490201234882”), “DEST_LOCN”:“未知”, “DEST_IDNT”:“未知”, “SEG_NUM”:“1 of 1”, “DLV_ATT”:0, “END_POINT”:“存储”, “FINAL_STATE”:“已交付”, “CDR_TYPE2”:“MO”, “DCS”:0 }
我用这些字段创建了一个唯一的复合索引:
MESSAGE_ID,CDR_TYPE,SUB_TIME,DEL_TIME,END_POINT
从SSRS(Microsoft BI工具)运行此查询:
从mycollection中选择TOP 1000 *,其中“2016-03-17 08:59:50”和“2016-03-17 09:59:50”之间的DEL_TIME
答案 3 :(得分:1)
根据您的文档结构和索引,我非常怀疑您的索引没有保留在内存中。我建议的三件事:
在mongo shell中,键入db.collection.stats().indexSizes
。这将为您提供该集合的所有索引的大小(以字节为单位)。如果这个数字高于你的RAM(实际上,即使它大于2GB,你可能正在交换),那么你的第一步是添加足够的RAM来保持你的索引在内存中。
其次,您确定需要复合指数吗?也就是说,您运行了大量使用所有这些字段的查询吗?或者你这样做只是为了确保独特性?如果您的所有查询都只在DEL_TIME字段上,那么在该字段上只有一个简单的索引将减少您的索引空间要求。
第三,您是否使用explain()选项运行查询?您需要直接在mongo shell中执行此操作。这将告诉您查询是否实际使用索引。只是查看查询,我认为应该,但是在你检查之前你永远不会知道。