因爲這個步驟太容易了,因此也很容易在無心間觸發索引構建。若是數據集很大,構建會花很長時間。在生產環境裏,這簡直就是夢魘,由於沒辦法停止索引構建。若是發生了這種狀況,你將不得不故障轉移到從節點上——若是有從節點的話。最明智的建議是將索引構建當作某類數據庫遷移來看待,確保應用程序的代碼不會自動聲明索引。數據庫
第一步,對要索引的值排序。通過排序的數據集在插入到B樹時會更高效。注意,排序的進度會以已排序文檔數和總文檔數的比率來進行顯示:性能
[conn1] building new index on { open: 1.0, close: 1.0 } for stocks.values 1000000/4308303 23% 2000000/4308303 46% 3000000/4308303 69% 4000000/4308303 92% Tue Jan 4 09:59:13 [conn1] external sort used : 5 files in 55 secs
第二步,排序後的值被插入索引中。進度顯示方式與第一步相同,完成以後,完成索引構建所用的時間會顯示出來,做爲插入system.indexes的耗時:ui
1200300/4308303 27% 2227900/4308303 51% 2837100/4308303 65% 3278100/4308303 76% 3783300/4308303 87% 4075500/4308303 94% Tue Jan 4 10:00:16 [conn1] done building bottom layer, going to commit Tue Jan 4 10:00:16 [conn1] done for 4308303 records 118.942secs
還要注意lockType,它說明索引構建用了寫鎖,也就是說其餘客戶端此時沒法讀寫數據庫。若是發生在生產環境裏,這無疑是很糟糕的,這也是長時間索引構建讓人抓狂的緣由。code
若是是在生產環境裏,經不住這樣暫停數據庫訪問的狀況,能夠指定在後臺構建索引。雖然索引構建仍會佔用寫鎖,但構建任務會停下來容許其餘讀寫操做訪問數據庫。若是應用程序大量使用MongoDB,後臺索引會下降性能,但在某些狀況下這是可接受的。例如,假設你知道能夠在應用程序流量最低的時間窗口內完成索引的構建,那麼這時後臺索引會是個不錯的選擇。排序
要在後臺構建索引,聲明索引時須要指定{background: true}。能夠像下面這樣在後臺構建以前的索引:索引
db.values.ensureIndex({open: 1, close: 1}, {background: true})
若是生產數據集太大,沒法在幾小時內完成索引,這時就須要其餘方案了。一般這會涉及讓一個副本節點下線,在該節點上構建索引,隨後讓其上的數據與主節點同步。一旦完成數據同步,將該節點提高爲主節點,再讓另外一個從節點下線,構建它本身的索引。該策略假設你的複製oplog夠大,能避免離線節點的數據在索引構建過程當中變得過舊。下一章會詳細討論複製,應該能幫你計劃這樣的遷移過程。文檔