聊一聊mongodb中的 explain 和 hint
看到explain和hint的時(shí)候,第一個(gè)想到的就是mysql,確實(shí),這就是在mysql中借鑒過來的,既然是借鑒過來的,我想大家都知道這兩個(gè)關(guān)鍵字的用處,話不多說,速速觀看~~~
一:explain演示
1. 構(gòu)建數(shù)據(jù)
為了方便演示,我需要生成10條數(shù)據(jù) to inventory,而且還是要在 no index 的情況下,比如下面這樣:
db.inventory.insertMany([ {?"_id"?:?1,?"item"?:?"f1",?type:?"food",?quantity:?500?}, {?"_id"?:?2,?"item"?:?"f2",?type:?"food",?quantity:?100?}, {?"_id"?:?3,?"item"?:?"p1",?type:?"paper",?quantity:?200?}, {?"_id"?:?4,?"item"?:?"p2",?type:?"paper",?quantity:?150?}, {?"_id"?:?5,?"item"?:?"f3",?type:?"food",?quantity:?300?}, {?"_id"?:?6,?"item"?:?"t1",?type:?"toys",?quantity:?500?}, {?"_id"?:?7,?"item"?:?"a1",?type:?"apparel",?quantity:?250?}, {?"_id"?:?8,?"item"?:?"a2",?type:?"apparel",?quantity:?400?}, {?"_id"?:?9,?"item"?:?"t2",?type:?"toys",?quantity:?50?}, {?"_id"?:?10,?"item"?:?"f4",?type:?"food",?quantity:?75?}]);2. 無索引查詢
db.inventory.find({?quantity:?{?$gte:?100,?$lte:?200?}?} ).explain("executionStats")從上圖中可以看到三個(gè)圈圈,這些都是我們在find中非常重要的信息,具體信息解釋如下:
1) COLLSCAN
這個(gè)是什么意思呢?如果你仔細(xì)一看,應(yīng)該知道就是CollectionScan,這就是所謂的“集合掃描”,對不對,看到集合掃描是不是就可以直接map到數(shù)據(jù)庫中的table scan/heap scan呢???是的,這就是所謂的性能最爛最無奈的由來。
2) nReturned
這個(gè)很簡單,就是說最后返回的num個(gè)數(shù),從圖中可以看到最終返回了三條。。。
3) docsExamined
那這個(gè)是什么意思呢??其實(shí)就是檢查了10個(gè)documents。。。最后返回了上面的nReturned。。。
ok,從上面三個(gè)信息中可以得出,原來我 examine 10 條數(shù)據(jù),最終才返回3條,說明7條數(shù)據(jù)的scan是無用的,問題就來了,如何減少examine的documents次數(shù)。。。完整的plans如下:
/*?1?*/ {"queryPlanner"?:?{"plannerVersion"?:?1,"namespace"?:?"datamip.inventory","indexFilterSet"?:?false,"parsedQuery"?:?{"$and"?:?[?{"quantity"?:?{"$lte"?:?200.0}},?{"quantity"?:?{"$gte"?:?100.0}}]},"winningPlan"?:?{"stage"?:?"COLLSCAN","filter"?:?{"$and"?:?[?{"quantity"?:?{"$lte"?:?200.0}},?{"quantity"?:?{"$gte"?:?100.0}}]},"direction"?:?"forward"},"rejectedPlans"?:?[]},"executionStats"?:?{"executionSuccess"?:?true,"nReturned"?:?3,"executionTimeMillis"?:?1,"totalKeysExamined"?:?0,"totalDocsExamined"?:?10,"executionStages"?:?{"stage"?:?"COLLSCAN","filter"?:?{"$and"?:?[?{"quantity"?:?{"$lte"?:?200.0}},?{"quantity"?:?{"$gte"?:?100.0}}]},"nReturned"?:?3,"executionTimeMillisEstimate"?:?0,"works"?:?12,"advanced"?:?3,"needTime"?:?8,"needYield"?:?0,"saveState"?:?0,"restoreState"?:?0,"isEOF"?:?1,"invalidates"?:?0,"direction"?:?"forward","docsExamined"?:?10}},"serverInfo"?:?{"host"?:?"localhost.localdomain","port"?:?27017,"version"?:?"3.2.8","gitVersion"?:?"ed70e33130c977bda0024c125b56d159573dbaf0"},"ok"?:?1.0 }3. 使用 single field 加速查找
知道前因后果之后,就可以進(jìn)行針對性的建立索引,比如拿 quality 字段舉例如下:
db.inventory.createIndex({?quantity:?1})db.inventory.find({?quantity:?{?$gte:?100,?$lte:?200?}?} ).explain("executionStats")這時(shí)候有意思了,當(dāng)執(zhí)行完 createindex 之后,再次 explain,有4個(gè)重要的parameters需要特別注意一下:
1) IXSCAN
這個(gè)時(shí)候再也不是所謂的COLLSCAN了,而是IndexScan,說明已經(jīng)命中索引了。
2) nReturned,totalDocsExamined,totalKeysExamined
從圖中可以看到三個(gè)參數(shù)都是3,這就說明 mongodb 查看了3個(gè)key,3個(gè)document,返回了3個(gè)文檔,這就是所謂的高性能吧。
二:hint演示
說到hint,也挺有意思,它用來強(qiáng)制mongodb 執(zhí)行指定的索引,為了方便演示,做兩組復(fù)合索引,比如這次在quality和type上構(gòu)建一下:
構(gòu)建完之后,我強(qiáng)制 mongodb 去使用 quantity 開頭的復(fù)合索引,從而強(qiáng)制mongodb 放棄那個(gè)以{type:1,quantity:1}的復(fù)合索引,很有意思哦,比如下圖:
從圖中可以看到,mongodb 檢查了6個(gè)keys最終找到了2個(gè)文檔,下面我不hint來看一下mongodb自己抉擇的最優(yōu)plan是怎么樣的。
再看上面的圖,你應(yīng)該明白了,mongodb果然執(zhí)行了那個(gè)最優(yōu)的plan,是不是很好玩,好了,本篇就說到這里,希望對你有幫助~
總結(jié)
以上是生活随笔為你收集整理的聊一聊mongodb中的 explain 和 hint的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Azure 内容审查器之羞羞图审查
- 下一篇: Blazor 火了,不禁让人想起已死的S