天天看點

MongoDB性能篇之索引分析

一、索引 MongoDB 提供了多樣性的索引支援,索引資訊被儲存在system.indexes 中,且預設總是為_id建立索引,它的索引使用基本和MySQL 等關系型資料庫一樣。其實可以這樣說說,索引是淩駕于資料存儲系統之上的另一層系統,是以各種結構迥異的存儲都有相同或相似的索引實作及使用接口并不足為 奇。 1.基礎索引 在字段age 上建立索引,1(升序);-1(降序): db.users.ensureIndex({age:1}) _id 是建立表的時候自動建立的索引,此索引是不能夠删除的。當系統已有大量資料時,建立索引就是個非常耗時的活,我們可以在背景執行,隻需指定“backgroud:true”即可。 db.t3.ensureIndex({age:1} , {backgroud:true}) 2.文檔索引 索引可以任何類型的字段,甚至文檔: db.factories.insert( { name: "wwl", addr: { city: "Beijing", state: "BJ" } } ); //在addr 列上建立索引 db.factories.ensureIndex( { addr : 1 } ); //下面這個查詢将會用到我們剛剛建立的索引 db.factories.find( { addr: { city: "Beijing", state: "BJ" } } ); //但是下面這個查詢将不會用到索引,因為查詢的順序跟索引建立的順序不一樣 db.factories.find( { addr: { state: "BJ" , city: "Beijing"} } ); 3.組合索引 跟其它資料庫産品一樣,MongoDB 也是有組合索引的,下面我們将在addr.city 和addr.state上建立組合索引。當建立組合索引時,字段後面的1 表示升序,-1 表示降序,是用1 還是用-1 主要是跟排序的時候或指定範圍内查詢 的時候有關的。 db.factories.ensureIndex( { "addr.city" : 1, "addr.state" : 1 } ); // 下面的查詢都用到了這個索引 db.factories.find( { "addr.city" : "Beijing", "addr.state" : "BJ" } ); db.factories.find( { "addr.city" : "Beijing" } ); db.factories.find().sort( { "addr.city" : 1, "addr.state" : 1 } ); db.factories.find().sort( { "addr.city" : 1 } ) 4.唯一索引 隻需在ensureIndex 指令中指定”unique:true”即可建立唯一索引。例如,往表t4 中插入2 條記錄: db.t4.ensureIndex({firstname: 1, lastname: 1}, {unique: true}); 5.強制使用索引 hint 指令可以強制使用某個索引。 db.t5.find( { age: { $lt:30}}).hint({name:1, age:1}).explain() 6.删除索引 //删除t3 表中的所有索引 db.t3.dropIndexes() //删除t4 表中的firstname 索引 db.t4.dropIndex({firstname: 1}) 二、explain執行計劃 MongoDB 提供了一個 explain 指令讓我們獲知系統如何處理查詢請求。利用 explain 指令,我們可以很好地觀察系統如何使用索引來加快檢索,同時可以針對性優化索引。 db.t5.ensureIndex({name:1}) db.t5.ensureIndex({age:1}) db.t5.find({age:{$gt:45}}, {name:1}).explain() { "cursor" : "BtreeCursor age_1", "nscanned" : 0, "nscannedObjects" : 0, "n" : 0, "millis" : 0, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { "age" : [ [45,1.7976931348623157e+308] ] } } 字段說明: cursor: 傳回遊标類型(BasicCursor 或 BtreeCursor) nscanned: 被掃描的文檔數量 n: 傳回的文檔數量 millis: 耗時(毫秒) indexBounds: 所使用的索引 三、優化器profile 在MySQL 中,慢查詢日志是經常作為我們優化資料庫的依據,那在MongoDB 中是否有類似的功能呢?答案是肯定的,那就是MongoDB Database Profiler。 1.開啟profiling功能 有兩種方式可以控制 Profiling 的開關和級别,第一種是直接在啟動參數裡直接進行設定。啟動MongoDB 時加上–profile=級别 即可。也可以在用戶端調用db.setProfilingLevel(級别) 指令來實時配置,Profiler 資訊儲存在system.profile 中。我們可以通過db.getProfilingLevel()指令來擷取目前的Profile 級别,類似如下操作: db.setProfilingLevel(2); 上面profile 的級别可以取0,1,2 三個值,他們表示的意義如下: 0 – 不開啟 1 – 記錄慢指令 (預設為>100ms) 2 – 記錄所有指令 Profile 記錄在級别1 時會記錄慢指令,那麼這個慢的定義是什麼?上面我們說到其預設為100ms,當然有預設就有設定,其設定方法和級别一樣有兩種,一種是通過添加 –slowms 啟動參數配置。第二種是調用db.setProfilingLevel 時加上第二個參數: db.setProfilingLevel( level , slowms ) db.setProfilingLevel( 1 , 10 ); 2.查詢 Profiling 記錄 與MySQL 的慢查詢日志不同,MongoDB Profile 記錄是直接存在系統db 裡的,記錄位置system.profile ,是以,我們隻要查詢這個Collection 的記錄就可以擷取到我們的 Profile 記錄了。列出執行時間長于某一限度(5ms)的 Profile 記錄: db.system.profile.find( { millis : { $gt : 5 } } ) MongoDB Shell 還提供了一個比較簡潔的指令show profile,可列出最近5 條執行時間超過1ms 的 Profile 記錄。 四、常用性能優化方案 建立索引 限定傳回結果數 隻查詢使用到的字段 采用capped collection 采用Server Side Code Execution 使用Hint,強制使用索引 采用Profiling 五、性能監控工具 1.mongosniff 此工具可以從底層監控到底有哪些指令發送給了MongoDB 去執行,從中就可以進行分析:以root 身份執行: $./mongosniff --source NET lo 然後其會監控位到本地以localhost 監聽預設27017 端口的MongoDB 的所有包請求。 2.Mongostat 此工具可以快速的檢視某組運作中的MongoDB 執行個體的統計資訊 字段說明: insert: 每秒插入量 query: 每秒查詢量 update: 每秒更新量 delete: 每秒删除量 locked: 鎖定量 qr | qw: 用戶端查詢排隊長度(讀|寫) ar | aw: 活躍用戶端量(讀|寫) conn: 連接配接數 time: 目前時間 它每秒鐘重新整理一次狀态值,提供良好的可讀性,通過這些參數可以觀察到一個整體的性能情況。 3.db.serverStatus 這個指令是最常用也是最基礎的檢視執行個體運作狀态的指令之一。 4.db.stats db.stats 檢視資料庫狀态資訊。 以上所述是小編給大家介紹的MongoDB性能篇之建立索引,組合索引,唯一索引,删除索引和explain執行計劃的相關知識,希望對大家有所幫助!