首页 > 解决方案 > 尽可能快地在 MongoDB 中加载一百万条记录

问题描述

我有一个包含超过 3000 万条记录的大型数据库,我如何知道我的服务器的瓶颈在哪里以及为什么我的查询需要时间。

我的数据库索引良好,当我选择记录时,并不是所有检查的记录。

我知道加载一百万条记录是不寻常的事情,但是如果我想尽快加载这些记录,如何知道为什么查询需要时间?有监控工具吗?

换句话说,如果有人问:我有一个很好的 CPU 和 SSD,为什么这个查询需要这么长时间,答案应该是什么?

在我看来,我认为这与 SSD 速度和用于查找记录的核心数量有关,而 NodeJS 仅使用一个核心。那正确吗?

查询示例:

db.bios.find( { birth: { $gt: new Date('2019-01-01'), $lt: new Date('2000-01-01') } } )

birth在我的情况下,这里是唯一索引的。

标签: node.jslinuxmongodbperformance

解决方案


我有一个很好的 CPU 和 SSD 为什么这个查询需要这么长时间,答案应该是什么?

您还需要考虑是否有足够的 RAM 来容纳索引。之后你需要做一些查询优化

如何知道为什么查询需要时间?有监控工具吗?

查看分析您的数据库。这将记录慢查询,您可以看到选择了哪些索引以及每个查询花费了多长时间。

这应该让您对数据库性能有一个很好的了解。您可以使用一些工具来可视化这些数据(这里有一篇博客文章详细介绍了使用 Logstash 和 Kibana)。

NodeJS 只使用一个核心。那正确吗?

NodeJS 主要在单个线程中运行,但您可以通过clusterworker生成更多线程。但是数据库在多个线程上运行在它自己的进程中,并且应该在与 Node 应用程序不同的服务器上运行。

用于加载许多文档的快速查询

每个数据库请求要加载多少个文档会有一个最佳点。这取决于文档的大小和查询。

来自mongoDB 文档

排序操作

如果 MongoDB 无法使用索引以请求的排序顺序获取文档,则排序操作中所有文档的总大小加上少量开销必须小于 32 兆字节。

例如,这可以处理大约 500 个文档。

添加排序顺序以在birth字段上按递增顺序排列。确保索引您的排序字段 ( birth),然后使用 获取前 500 个文档limit。取最后一个返回的文档,并使用它的值birth来限制您的下一个查询。然后继续循环,直到找到所有文档。

第一个查询是

db.bios.find( { birth: { $gt: new Date('2019-01-01'), $lt: new Date('2000-01-01') } } )

birth如果返回的最后一个对象有'2019-01-05'

第二个查询是

db.bios.find( { birth: { $gt: new Date('2019-01-05'), $lt: new Date('2000-01-01') } } 

等等。

如果你使用Mongoose,我写了一个小的npm 包来简化这个操作(但它没有测试,因为它最初只用于个人项目)


更新:硬件要求

没有简单的方法来找出什么会阻碍您的 MongoDB 实例,因为它取决于您的使用情况 - 大量索引和复合索引 - 较小的文档或较大的文档 - 经常写入一次读取或经常更新(您的文档是否会增长?) - 复杂的聚合

测试这一点的最佳方法是通过缩放测试,因为 MongoDB 应该线性缩放。如果您预计会有 1TB 的集合,请尝试使用相同的索引和架构创建一个 1GB 大小的示例集合。在便宜、弱的服务器上运行它。对它运行查询并查看资源使用情况(CPU、RAM、磁盘 I/O、网络)

您可以查看有关此主题的一些不错的文档和博客文章:

架构

如果您需要非常快速且频繁地加载大量数据,您还应该考虑重新设计架构。

我怀疑您是否在 UI 中显示 100 万行数据。如果您正在加载数据来处理它,可以将处理后的数据保存为新集合(例如,用于图表)。如果您需要搜索它,请使用查询/过滤器。如果需要跨多个字段进行全文搜索,请将其合并到一个字段中。或者考虑使用针对此类操作优化的数据库(例如 Casandra)


推荐阅读