var db = db.getSiblingDB("testdb"
for (var i = 0; i < 100000; i++) {
var start = (new Date()).getTime();
var collName = "test" + i;
var doc = {name: "name" +i, seq: i};
db.createCollection(collName); // 創(chuàng)建集合
db[collName].createIndex({name: 1}); // 創(chuàng)建索引
db[collName].insert(doc); // 插入一條記錄
var end = (new Date()).getTime(); // 統(tǒng)計耗時
print("cost: " + (end - start));
}
隨著集合數(shù)越來越多,測試過程中發(fā)現(xiàn)2個問題
/* Get the handle and lock it while the cursor is using it. */
if (WT_PREFIX_MATCH(uri, "file:") {
/*
* If we are opening exclusive, get the handle while holding
* the checkpoint lock. This prevents a bulk cursor open
* failing with EBUSY due to a database-wide checkpoint.
*/
if (LF_ISSET(WT_DHANDLE_EXCLUSIVE))
WT_WITH_CHECKPOINT_LOCK(session, ret,
ret = __wt_session_get_btree_ckpt(
session, uri, cfg, flags));
另外從目前的實現(xiàn)看,后臺建索引時并不是 bulk cursor,而是使用普通的 cursor 逐條插入,故不會去競爭 checkpoint 的鎖,上述測試代碼在createIndex 時加上{background: true}選項時問題解決。
建議用戶在建立索引時,盡量選擇后臺建索引的方式,可能性能上不如前臺方式,但后臺建索引對業(yè)務(wù)的影響是最小的(前臺建索引還會獲取 db 的寫鎖,導(dǎo)致 db 上的讀寫都被阻塞),最好的方式是 DDL 和 DML 分離,在業(yè)務(wù)代碼中不要出現(xiàn)建索引、建集合的邏輯,預(yù)先創(chuàng)建好,業(yè)務(wù)只做CRUD 操作。