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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 全域性索引和本地索引的比較索引
- 索引的分析和比較索引
- [轉]Oracle分割槽索引--本地索引和全域性索引比較Oracle索引
- Oracle分割槽索引--本地索引和全域性索引比較(轉)Oracle索引
- 【索引】oracle查詢使用索引和不使用索引的比較索引Oracle
- 本地索引和全域性索引的適用場景索引
- 索引失效場景索引
- 索引設計(組合索引適用場景)索引
- 比較有索引和無索引的查詢速度(在mysql資料庫中)索引MySql資料庫
- phoenix全域性索引和本地索引 概述,使用場景,區別等詳解索引
- 【索引】Bitmap點陣圖索引與普通的B-Tree索引鎖的比較索引
- 【索引】Oracle之不可見索引和虛擬索引的比對索引Oracle
- Mysql中的Btree與Hash索引比較MySql索引
- MySQL系列:索引失效場景總結MySql索引
- ElasticSearch所使用的倒排索引的思想和使用場景Elasticsearch索引
- 大量索引場景下 Easysearch 和 Elasticsearch 的吞吐量差異索引Elasticsearch
- B-Tree索引與Bitmap點陣圖索引的鎖代價比較研究索引
- mysql 聯合索引的兩種特殊場景MySql索引
- 很多人比較糾結的約束和索引的關係索引
- insert的不同場景效能比較
- 【Bitmap Index】B-Tree索引與Bitmap點陣圖索引的鎖代價比較研究Index索引
- mongodb建立索引和刪除索引和背景索引backgroundMongoDB索引
- MySQL 字串索引和字首索引MySql字串索引
- 關於索引空間的重用的幾個場景索引
- 函式索引的兩個應用場景示例(下)函式索引
- 不走索引場景的一次分析優化索引優化
- 《Oracle 複合壓縮索引場景及效能對比》-原理引航-例項演示-可下載Oracle索引
- 主鍵索引 (聚集索引) 和普通索引 (輔助索引) 的區別索引
- Python Numpy 切片和索引(高階索引、布林索引、花式索引)Python索引
- 比較SQL Server 2008資料庫引擎優化和索引優化SQLServer資料庫優化索引
- Oracle全域性索引和本地索引Oracle索引
- MySQL 唯一索引和普通索引MySql索引
- 全域性索引失效帶來的幾個測試場景索引
- MySQL資料庫索引以及失效場景詳解DELNMySql資料庫索引
- EF Core 索引器屬性(Indexer property)場景及應用索引Index
- jmeter混合場景的多種實現方式比較JMeter
- MySQL 聚簇索引 和覆蓋索引MySql索引
- MySQL字首索引和索引選擇性MySql索引