我有一个包含4亿份文件的藏品。每个都有6个DateTime,1个Boolean,8个Double,9个Integer和6个String字段。我正在尝试构建以下索引:
db.MyCollection.ensureIndex(
{ "String1" : 1, "String2" : 1, "String3" : 1, "DateTime1" : 1, "Integer1" : 1, "DateTime2" : 1 },
{background: true}
);
运行5天后,只完成了一半。
服务器运行的是Windows Server Enterprise,具有4TB磁盘空间和256GB RAM。很少有其他进程针对数据库运行。没有分片或其他特殊配置。
有没有办法加快速度? (不要放弃background = true
限定符,因为我不希望它完全关闭我的数据库,在这种情况下就是这样。)
答案 0 :(得分:8)
即使没有谈论多键索引,也会发生这种情况。正在进行大规模的表扫描。因此,mongoDB遍历文档,尝试查找要编制索引的字段,评估该字段(如果当前文档中不存在,则为null
),并将其结果写入不少于6个文件我们正在谈论6个指数。算一算:200.000.000 / 86400 * 5告诉我们mongoDB大约每秒460个文档或者每个文档只需要 2.2毫秒。我不会那么慢。这可能需要很长时间,但速度并不慢。
{background:true}
使用此参数不会将您锁定在数据库之外。恰恰相反,文档中明确说明了Index Creation section和tutorial section on creating indices in the background。但是,有一句话很容易被误解:
此外,在前台索引构建期间,不会对所有数据库(例如listDatabases)进行读取或写入锁定的操作。
这意味着您无法执行适用于所有数据库的操作和需要读取或写入锁定。
将共享群集与副本集分片一起使用。除了提高性能外,它易于设置并具有多种优势。其中之一是简单的可扩展性,添加分片(从而为群集增加空间和计算能力)非常容易非常。备份对应用程序的影响较小。不再有单点故障(如果做得对,这甚至适用于整个数据中心规模的中断)。
抱歉,在Windows服务器上运行磁盘依赖性能的应用程序对我来说根本没有意义。 ExtFS4或XFS比NTFS或ReFS快25%到40%,具体取决于优化。这会对像您的用例一样依赖磁盘IO的应用程序产生真正的差异。我们谈的是几天(甚至没有考虑更高效的内存映射和Linux系统上操作系统的内存消耗减少)。
{background:true}
虽然这并没有真正提高性能(实际上,由于显而易见的原因,实际构建索引的时间比前台要长),您的应用程序在构建索引期间仍然可用。因此,根据您的需求,这可能是一个可行的选择。
旁注:这是一个 Bad Idea™,在使用mongoDB时会垂直缩放,因为它是明确设计为水平缩放的。这尤其适用于像您这样的大型集合,因为并行处理会大大提高应用程序的性能。