如何优化和维护10亿条记录的MongoDB集合?

时间:2016-04-29 14:17:13

标签: mongodb

我有一个拥有10亿条记录的MongoDB集合。它是电信SMSC节点的最后15天日志,它基本上保持通过SMSC发送的所有短信的传送状态。我正在努力根据DateTime过滤器选择数据。它真的很慢。当我尝试从此集合中删除大量记录以删除超过两周的日志时,它也非常慢。删除查询字面上永远不会结束。说到这一切,我正在使用的电脑是非常常见的台式机戴尔PC,它配备了带有4GB内存的Core i7处理器。有什么建议吗?

4 个答案:

答案 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中执行此操作。这将告诉您查询是否实际使用索引。只是查看查询,我认为应该,但是在你检查之前你永远不会知道。