我有一个拥有10亿条记录的MongoDB集合。它最近15天从电信SMSC节点登录,基本保持SMSC发送的所有短信的递送状态。我努力选择基于DateTime过滤器的数据。它真的很慢。当我尝试删除该集合中的记录块以删除超过两周的日志时,它也非常慢。从字面上删除查询从不结束。说到这一切,我使用的个人电脑是非常平常的台式机戴尔电脑,它有一个带有4GB内存的Core i7处理器。任何建议?如何优化和维护一个包含10亿条记录的MongoDB集合?
回答
这是关键:
创建索引来支持查询
限制查询的结果数减少网络需求
用突起只返回所需的数据
使用$提示选择特定索引
使用增量运算符执行运算服务器端
你可以找到一个解释:https://docs.mongodb.org/manual/tutorial/optimize-query-performance-with-indexes-and-projections/
您可以发布您的文档结构?
我怀疑两件事。首先,对于10亿条记录,我认为你的RAM非常匮乏。如果你没有将工作集保存在内存中,MongoDB的性能就会下降。至少,这包括你的索引。但为了获得良好的性能,您还应该包含足够的工作集(即您的数据库常规访问的文档数量,例如,如果您的查询通常在任何给定时间在一百万份这些文档上工作)。即使是一个很小的索引(比如一个_id字段的主索引)对于10亿条记录来说也会远远超过4GB。
其次,你确定你有适当的索引?而你的查询使用你的索引?您似乎希望在时间戳字段中加上索引,以及可能查询的任何字段(例如,如果您的删除查询还包含除时间戳之外的其他搜索字词)。
我建议的第一步是获取索引的大小。您可以通过输入db.collection.stats().indexSizes
在mongo shell中执行此操作。您需要的最小RAM是您的索引大小+您的工作集的一些金额。
一旦你有足够的RAM,接下来确保你的查询使用你的索引。您可以使用Mongo的explain()功能查看任何查询的查询计划,并且可以确定您是否实际访问了索引,或者Mongo是否绕过它们并执行完整的文档搜索。
如果您已经定义了合适的索引,有足够的内存来保存您的工作集(索引+您通常访问的文档集),并且确信您的查询正在使用您的索引,那么可能适合转向其他策略,如分片。但是考虑到你现在的计算机统计数据(特别是4GB内存),我怀疑你会走上一个很长的路,只是上面列出的第一步。
以下是集合中的示例数据。
样本数据:
{ “_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_L OCN”:NumberLong( “161350003000”), “ORIG_IDNT”:NumberLong( “3024902”), “DEST_LOCN”: “UNKNOWN”, “DEST_IDNT”: “UNKNOWN”, “SEG_NUM”: “1 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 *,其中DEL_TIME位于'2016-03-17 08:59:50'和'2016-03-17 09:59之间:50'
根据你的文档结构和索引,我高度怀疑你的索引没有被保存在内存中。我建议的三件事:
在mongo shell中输入db.collection.stats().indexSizes
。这将为您提供该集合的所有索引的大小(以字节为单位)。如果这个数字高于你的RAM(实际上,即使它大于2GB,你可能会交换),那么你的第一步是添加足够的RAM来保持你的索引在内存中。
二,你确定你需要一个复合索引吗?也就是说,你是否运行了很多使用所有这些字段的查询?还是你这样做只是为了确保唯一性?如果您的所有查询都在DEL_TIME字段中,那么只在该字段上使用简单索引将会减少您的索引空间要求。
第三,你有解释()选项运行你的查询吗?您需要在mongo shell中直接执行此操作。这会告诉你,如果你的查询实际上使用索引。看看查询,我认为应该是,但是直到你检查,你才会知道。
- 1. SQL查询 - 包含300列和1.2亿条记录的表
- 2. 从包含2亿条记录的表中选择一些记录
- 3. 如何用Spark找到最近邻居的10亿条记录?
- 4. 数据库含7亿条记录
- 5. 导出数据块中包含数亿条记录的MySQL表?
- 6. 维护MongoDB集合的顺序
- 7. 我如何从mongodb中导出3亿条记录?
- 8. MongoDB:优化搜索多个集合
- 9. 如何优化包含LIKE'%abc%'查询的160多万条记录的MySQL表
- 10. 如何创建一个包含集合
- 11. 在Python中,如何编写一个包含集合的集合?
- 12. 我如何输出一个集合#(10)每行一维数组?
- 13. 我想在oracle数据库中插入10亿条记录
- 14. 如何向拥有10亿条记录的BAM BizTalk表添加新列
- 15. 如何简化mongodb集合?
- 16. 在mongodb中为1亿条记录添加新字段
- 17. Java:用于存储和读取10亿条数据记录的最佳方法
- 18. Loopback Model Relation:如何在另一个集合中包含集合
- 19. 优化将多个记录合并到一个记录中的mysql视图
- 20. 如何确定一个集合是否包含Python中的另一个集合
- 21. 检查特定领域的MongoDB集合存在,但不包括一个记录
- 22. 在MongoDB中对一个集合中的记录进行分区
- 23. 组合优化 - 枚举包含给定集合的所有子集
- 24. MongoDB - 指定集合可能只包含一个文档
- 25. 请帮我优化包含的子查询仅几百记录
- 26. 用monetdb生成1亿条记录
- 27. 批量插入数亿条记录
- 28. 优化选择查询得到10×10的记录形成数百万条记录
- 29. 添加记录和操纵记录集以包含公式
- 30. 如何保护包含git历史记录的文件夹
非常感谢您的意见。在下面发布样本数据。 –