multi-key索引和wildCard索引場景比較
本文來自獲得《2021MongoDB技術實踐與應用案例徵集活動》優秀案例獎作品
作者:雷徹
引文
Multi-key index
multi-key 支援對陣列的高效查詢。
舉例:
db.employee1.insertMany([{"name":"xiaoming","age":25,"ctime":new ISODate(),goodAt:["mongodb","hbase","c++"]},{"name":"xiaohong","age":28,"ctime":newISODate(),goodAt:["es","java","c++"]},{"name":"xiaoguang","age":29,"ctime":newISODate(),goodAt:["mysql","c++","mongodb"]}])--indexdb.employee1.createIndex({goodAt:1})--查詢db.employee1.find({"goodAt":"mysql"})
explain的結果中,winningPlan.inputStage.stage為IXSCAN ,走索引goodAt_1。這裡字
段"mysql"是一個完整的陣列元素。下面再做兩個測試:
侵入查詢測試
如果陣列元素為json串,不能通過multi-key索引查詢某個元素的屬性
db.employee1.insertMany([{"name":"a","age":25,"ctime":new ISODate(),"goodAt":[ {database:"mysql", lang:"c++"}, {database:"hbase",lang:"java"}, {database:"tidb",lang:"golang"} ]}])--擷取json屬性,不支援;db.employee1.find({"goodAt":{"database":"mysql"}}).explain() /**走索引,結果為空,沒有滿足條件的元素**/db.employee1.find({"goodAt":{"database":"mysql", "lang" : "c++" }}).explain() /**走索引,結果不為空**
建議使用如下寫法:
--遞迴db.employee1.find({"goodAt.database":"mysql"}).explain() /**不走索引,結果不為空**/
db.employee1.createIndex({"goodAt.database":1})db.employee1.find({"goodAt.database":"mysql"}).explain() /**走索引,結果不為空**/
tips:
-
multi-key適用於對陣列進行索引
-
不能對陣列進行雜湊
-
不支援對巢狀的物件進行查詢;
WildCard index
在 上文中,查詢陣列元素某個欄位,就需要對欄位單獨加索引,用起來很不方便。在MongoDB4.2版本引入了wildCard索引,支援物件,陣列的檢索,並且可以侵入元素內部遍歷,非常方便。
多屬性集合,ok:{k1:v1,k2:v2},對ok建索引
舉例:
db.employee2.insertMany([{"name":"xiaoming","age":25,"ctime":new ISODate(),"goodAt":{"database":["mongodb","hbase"],"programLanguage":"c++"}},{"name":"xiaohong","age":28,此時尚未建索引,查詢goodAt某個屬性,可以看到stage為COLLSCAN新增wildCard索引後"ctime":new ISODate(),"goodAt":{"database":"mysql","programLanguage":"java","middleAware":"zookeeper"}},{"name":"xiaoguang","age":29,"ctime":new ISODate(),"goodAt":{"database":"mongodb","programLanguage":"python","web":"nodejs"}}])
此時尚未建索引,查詢goodAt某個屬性,可以看到stage為COLLSCAN
db.employee2.find({"goodAt.database": "mysql"}).explain()
新增wildCard索引後
--對goodAt建索引db.employee2.createIndex({ "goodAt.$**": 1 })db.employee2.find({"goodAt.database": "mongodb"}).explain()
在元素"name":"xiaoming"中,goodAt.database欄位的值為陣列,我們看看能否走索引匹配
db.employee2.find({"goodAt.database": "mongodb"}).explain()
wildCard索引也支援一個multi-key索引,可以對其中的陣列元素進行索引匹配。
侵入查詢測試
進一步在wildCard索引中的陣列元素下,新增物件,能否走索引?我們在goodAt.database屬性中,增加陣列屬性,做屬下測試,目標是確認wildCard能否在陣列中遞迴;
db.employees2.insert({"name":"xiaohong1","age":29,"ctime":new ISODate(),"goodAt":{"database":[{"rdb":"mysql"}, {"nosql":["mongodb","redis"]}, {"newsql":"tidb"} ],"programLanguage":"go" }})db.employee2.find({"goodAt.database.nosql": "mongodb"}).explain()
顯然,wildCard索引支援對陣列元素中的檢索。
db.employees2.insert({"name":"a","age":29,"ctime":new ISODate(),"goodAt":{"database":{"rdb":"mysql","nosql":"mongodb","newsql":"tidb"},"programLanguage":"go" }})db.employee2.find({"goodAt.database.nosql": 1}).explain()
再回到我們multi-key中的例子,把索引改為wildCard,是否可行?
db.employee1.dropIndexes('goodAt_1')db.employee1.createIndex({ "goodAt.$**": 1 })db.employee1.find({"goodAt.database":"mysql"}).explain()
可以滿足需求。注意:
-
wildCard不能支援兩層以上的陣列巢狀
-
wildCard也不支援對如下查詢的索引訪問
db.employee1.find({"goodAt":{"database":"mysql"}}).explain()
查詢子屬性,建議使用 {"goodAt.database":1} 而不是 {goodAt:{"database":1}} ,對索引更友 好。
小結
multi-key和wildCard索引分別適用不同的場景,讓entry建模變得更加簡單。在使用時,需要注意:
-
multi-key索引主要加快陣列遍歷,功能純粹;
-
wildCard可以侵入遍物件或陣列內部,避免單屬性建立索引,更加靈活;
-
wildCard不會遍歷連續巢狀兩層以上的陣列;
-
不建議太多層巢狀,儘量控制在3層以內;
關於作者: 雷徹
搜狐集團資料庫團隊高階運維工程師,具有豐富的資料庫運維經驗,精通資料庫架構設計、效能優化及故障診斷,目前負責MySQL及MongoDB運維管理工作,並參與公司資料庫雲平臺開發建設,將運維經驗整合到公司資料庫雲平臺中。專注於CDC服務構建。願和大家多交流學習,為社群貢獻一份力量!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69961190/viewspace-2851960/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 索引失效場景索引
- 索引設計(組合索引適用場景)索引
- phoenix全域性索引和本地索引 概述,使用場景,區別等詳解索引
- Mysql中的Btree與Hash索引比較MySql索引
- MySQL系列:索引失效場景總結MySql索引
- 大量索引場景下 Easysearch 和 Elasticsearch 的吞吐量差異索引Elasticsearch
- mongodb建立索引和刪除索引和背景索引backgroundMongoDB索引
- mysql 聯合索引的兩種特殊場景MySql索引
- Python Numpy 切片和索引(高階索引、布林索引、花式索引)Python索引
- MySQL 字串索引和字首索引MySql字串索引
- 主鍵索引 (聚集索引) 和普通索引 (輔助索引) 的區別索引
- MySQL 唯一索引和普通索引MySql索引
- MySQL 聚簇索引 和覆蓋索引MySql索引
- 從InnoDB 索引執行簡述 聚集索引和非聚集索引、覆蓋索引、回表、索引下推索引
- 唯一索引和普通索引的選擇索引
- 淺析InnoDB引擎的索引和索引原理索引
- 全域性索引失效帶來的幾個測試場景索引
- EF Core 索引器屬性(Indexer property)場景及應用索引Index
- MySQL資料庫索引以及失效場景詳解DELNMySql資料庫索引
- 使用Elasticsearch的動態索引和索引優化Elasticsearch索引優化
- oracle 索引和不走索引的幾種形式Oracle索引
- 聯合索引和多個單列索引使用中的索引命中情況及索引建立原則索引
- jmeter混合場景的多種實現方式比較JMeter
- MySQL實戰45講——普通索引和唯一索引MySql索引
- MySQL中的聚簇索引和非聚簇索引MySql索引
- 普通索引和唯一索引,應該怎麼選擇?索引
- MySQL管理表和索引MySql索引
- 索引原理和優勢索引
- SAP CDS重定向檢視和直接讀這兩者場景的效能比較
- 理解索引:索引優化索引優化
- mysql索引之字首索引MySql索引
- ElasticSearch 索引 VS MySQL 索引Elasticsearch索引MySql
- 什麼是行儲存和列儲存?正排索引和倒排索引?MySQL既不是倒排索引,也索引MySql
- js 深比較和淺比較JS
- MySQL資料SQL優化中,索引不被使用的典型場景總結MySql優化索引
- oracle全文索引之同步和優化索引做了什麼Oracle索引優化
- 資料庫系列:字首索引和索引長度的取捨資料庫索引
- SQL Server索引 - 非聚集索引SQLServer索引