建索引会阻塞读写吗?这篇在 800 万个文档的集合上建索引,同时用一个线程不停读写,对比建索引前后的延迟,再看进度、并发写入、唯一索引冲突和 drop 的结果。
建索引耗时 7.9 s
800 万个文档上建索引 7.9 s,并发线程的读写延迟几乎没有变化(p99 读 0.39 → 0.43 ms,写 0.17 → 0.19 ms),没有任何错误。
读 建之前 7,252 次,中位数 0.18 ms,p99 0.39 ms,最大 1.8 ms 读 建期间 29,390 次,中位数 0.17 ms,p99 0.43 ms,最大 5.1 ms 读 建之后 7,287 次,中位数 0.17 ms,p99 0.31 ms,最大 9.7 ms 写 建之前 7,251 次,中位数 0.09 ms,p99 0.17 ms,最大 4.7 ms 写 建期间 29,390 次,中位数 0.09 ms,p99 0.19 ms,最大 14.5 ms 写 建之后 7,288 次,中位数 0.11 ms,p99 0.20 ms,最大 4.8 ms 并发线程遇到的错误数: 0 []
currentOp 显示两个阶段:scanning collection 扫描集合,inserting keys from external sorter 把排好序的键写进索引,都带 done / total。
0.5s Index Build: scanning collection Index Build: scanning collection: 1337622/8009093 16% {"done": 1337622, "total": 8009093}
1.0s Index Build: scanning collection Index Build: scanning collection: 2623216/8010870 32% {"done": 2623216, "total": 8010870}
1.5s Index Build: scanning collection Index Build: scanning collection: 4025756/8012752 50% {"done": 4025756, "total": 8012752}
2.0s Index Build: scanning collection Index Build: scanning collection: 4857640/8013960 60% {"done": 4857640, "total": 8013960}
3.5s Index Build: scanning collection Index Build: scanning collection: 5550659/8020329 69% {"done": 5550659, "total": 8020329}
4.0s Index Build: scanning collection Index Build: scanning collection: 6954793/8022184 86% {"done": 6954793, "total": 8022184}
4.5s Index Build: scanning collection null
5.5s Index Build: inserting keys from external sorter into index Index Build: inserting keys from external sorter into index: 1059877/8023600 13% {"done": 1059877, "total": 8023600}构建期间插入的文档也会进入索引,最终索引条目数等于文档数。
文档数 8,043,929;索引条目 {'_id_': 8043929, 'k_1': 8043929}
test> db.t.find({k: {$gte: 0, $lt: 100000}})
{
plan: 'FETCH > IXSCAN(k_1)',
nReturned: 799,
keysExamined: 799,
docsExamined: 799,
ms: 39
}构建期间对重复值的并发插入不会被拒绝;构建结束时发现重复而失败(E11000),索引没有建出来,重复的文档还在。
建唯一索引耗时 5.3 s;并发线程插入 u=123 的重复文档(原来已有一个 u=123)成功了 50 次
建唯一索引的结果: Index build failed: cd764f0b-11a1-4211-8655-ed48d2c5e00d: Collection test.t ( 779cb36c-4a3e-471a-ba26-639234e32930 ) :: caused by :: E11000 duplicate key error collection: test.t index: u_1 dup key: { u: 123 }, full error: {'ok':
索引列表: ['_id_', 'k_1'];u=123 的文档数 51在构建期间 drop 集合会立即成功(0.05 s),并中止构建,构建一侧收到失败的错误。
建 z 索引 1.5 s 后在另一个连接上 drop 整个集合:drop ok,耗时 0.05 s;建索引的线程: Index build failed: 12875bcd-15ac-4c69-92e3-f0751a9ddca6: Collection test.t ( 779cb36c-4a3e-471a-ba26-639234e32930 ) :: caused by :: Collection test.t(779cb36c-,1.53 s
这是单节点、1 GB 数据、SSD 上的结果。副本集上的 commitQuorum、构建在 secondary 上的行为没有测。