目錄
一、索引介紹
? ? ? ? 1.1 單字段索引
? ? ? ? 1.2 復(fù)合索引
? ? ? ? 1.3?多鍵索引
? ? ? ? 1.4 主鍵索引
? ? ? ? 1.5 TTL 索引
? ? ? ? 1.6 地理空間索引
? ? ? ? 1.7 哈希索引
? ? ? ? 1.8 創(chuàng)建索引時(shí)注意事項(xiàng)
? ? ? ? 1.9 索引效果查看
?二、索引實(shí)現(xiàn)原理
? ? ? ? 2.1 為什么使用 B-Tree
三、執(zhí)行計(jì)劃
一、索引介紹
????????任何數(shù)據(jù)庫都有索引這一核心功能,索引通常能夠極大的提高查詢效率,如果沒有索引,MongoDB 在讀取數(shù)據(jù)時(shí)必須掃描集合中的每個(gè)文件,并選取那些符合查詢條件的記錄。
????????這種掃描查詢集合的查詢方式效率非常低,特別在處理大量數(shù)據(jù)時(shí)。索引是特殊的數(shù)據(jù)結(jié)構(gòu),索引存儲(chǔ)在一個(gè)易于遍歷讀取的數(shù)據(jù)集合中,索引是對(duì)數(shù)據(jù)庫表中一列或多列的值進(jìn)行排序的一種結(jié)構(gòu)。
? ? ? ? 使用索引通常有如下的作用:
- 加速查詢:通過索引,數(shù)據(jù)庫能夠快速定位到符合條件的文檔,避免全表掃描,大大減少查詢響應(yīng)時(shí)間。
- 排序優(yōu)化:索引可用于高效地對(duì)查詢結(jié)果進(jìn)行排序,無需在內(nèi)存中對(duì)大量數(shù)據(jù)進(jìn)行排序操作。
- 覆蓋查詢:當(dāng)索引包含了查詢所需的所有字段時(shí),數(shù)據(jù)庫可以直接從索引中獲取全部數(shù)據(jù),無需訪問文檔本身,減少了磁盤 I/O。
- 唯一性約束:創(chuàng)建唯一索引可以確保集合中指定字段的值唯一,防止插入重復(fù)數(shù)據(jù)。
? ? ? ? 在 MongoDB 中有很多種索引,下面分別看下不同的索引。
? ? ? ? 1.1 單字段索引
????????在單個(gè)字段上建立的索引,對(duì)于單字段索引和排序操作,索引鍵的排序順序無關(guān)緊要,因?yàn)镸ongoDB 可以在任意方向遍歷。
// users 為 collection,創(chuàng)建 username 索引
db.users.createIndex({username: 1})
????????
? ? ? ? 1.2 復(fù)合索引
????????多個(gè)字段的自定義索引,即復(fù)合索引。復(fù)合索引中的字段順序很重要。例如,如果復(fù)合索引由{ userid: 1, score: -1}?組成,則索引首先按userid排序,然后在每個(gè)userid值內(nèi)按score排序。在查詢時(shí)可以按照userid:1,score:-1或者userid:-1,score:1查詢,因?yàn)檫@兩個(gè)順序和樹的組成順序完全相同,相反執(zhí)行userid:-1,score:-1將不會(huì)使用索引。
? ? ? ? 1.3?多鍵索引
????????MongoDB 使用多鍵索引來索引存儲(chǔ)在數(shù)組中的內(nèi)容。如果索引一個(gè)包含數(shù)組值的字段,MongoDB 會(huì)為數(shù)組的每個(gè)元素創(chuàng)建單獨(dú)的索引條目。這些多鍵索引允許查詢通過匹配數(shù)組的一個(gè)或多個(gè)元素來選擇包含數(shù)組的文檔。如果索引字段包含數(shù)組值,MongoDB 會(huì)自動(dòng)判斷是否創(chuàng)建多鍵索引;你不需要明確指定多鍵類型。
? ? ? ? 1.4 主鍵索引
????????MongoDB 中默認(rèn)為 _id 字段且不能更改,用于維護(hù)聚簇索引樹。每個(gè)集合都有一個(gè)默認(rèn)的索引:“_id”索引,它是一個(gè)特殊的字段,用來唯一標(biāo)識(shí)集合中的每個(gè)文檔。這個(gè)字段通常被用作查詢文檔的主鍵,并且MongoDB會(huì)自動(dòng)為其創(chuàng)建一個(gè)唯一索引。
? ? ? ? 1.5 TTL 索引
????????類似于 Redis 的過期時(shí)間,為一個(gè)字段創(chuàng)建TTL索引后,超時(shí)會(huì)自動(dòng)刪除整個(gè)文檔。TTL索引適用于那些具有有效期、需要定期清理過期數(shù)據(jù)的場景,如會(huì)話記錄、日志條目、臨時(shí)消息等。
db.event_log.createIndex({timestamp: 1}, {expireAfterSeconds: 604800}) // 604800秒 = 7天
? ? ? ? 1.6 地理空間索引
????????特別針對(duì)地理空間數(shù)據(jù)設(shè)計(jì)的索引,如2dsphere
索引用于處理經(jīng)緯度坐標(biāo),支持地理位置查詢(如距離計(jì)算、邊界框查詢等)。其他地理空間索引類型包括2d
(用于平面坐標(biāo))和geoHaystack
(已棄用)。
? ? ? ? 1.7 哈希索引
????????將索引字段的值通過哈希函數(shù)計(jì)算出哈希值進(jìn)行索引,適用于等值查詢,但不支持范圍查詢和排序。
? ? ? ? 1.8 創(chuàng)建索引時(shí)注意事項(xiàng)
? ? ? ? 在創(chuàng)建索引時(shí)不要過多添加,雖然索引可以有效的提升查詢性能,但過多的索引會(huì)增加寫入成本、占用更多的存儲(chǔ)空間,并可能使查詢優(yōu)化器的選擇變得復(fù)雜。
? ? ? ? 創(chuàng)建索引時(shí)可能會(huì)存在鎖表,需要根據(jù)具體使用的版本而定。4.2及以上版本在創(chuàng)建索引過程中,僅在索引構(gòu)建的開始和結(jié)束時(shí)持有排他鎖,構(gòu)建過程中的其余部分產(chǎn)生交錯(cuò)讀取和寫入操作。建議在業(yè)務(wù)低峰期添加索引。
? ? ? ? 1.9 索引效果查看
? ? ? ? 索引創(chuàng)建后,到底所創(chuàng)建索引的效果如何呢?可以通過一下方式驗(yàn)證,具體就是查看所以的區(qū)分度,類似于 MySQL 的 Cardinality。所得的值越接近1說明區(qū)分度越高,索引效果越好,
// 索引字段去重后的數(shù)量 / 集合的總量
db.collection.distinct("field").length/db.collection.count()
?二、索引實(shí)現(xiàn)原理
????????MongoDB 是文檔型數(shù)據(jù)庫,使用 BSON 格式保存數(shù)據(jù),比關(guān)系型數(shù)據(jù)庫存儲(chǔ)更方便。MySQL 是關(guān)系型數(shù)據(jù)庫,數(shù)據(jù)的關(guān)聯(lián)性非常強(qiáng),區(qū)間訪問是常見的一種場景,底層索引組織數(shù)據(jù)使用B+樹,B+樹由于數(shù)據(jù)全部存儲(chǔ)在葉子節(jié)點(diǎn),并且通過指針串在一起,這就很容易進(jìn)行區(qū)間遍歷甚至全部遍歷。
? ? ? ? MongoDB 采用 B-tree 作為其索引的主要數(shù)據(jù)結(jié)構(gòu)。B-tree 是一種自平衡的多路搜索樹。
????????自平衡:無論數(shù)據(jù)如何插入或刪除,樹的高度始終保持相對(duì)穩(wěn)定,從而保證查詢效率接近O(log N),其中N是集合中文檔的數(shù)量。
????????多路分支:每個(gè)節(jié)點(diǎn)可以有多個(gè)子節(jié)點(diǎn),具體數(shù)量取決于 B-tree 的階數(shù)。高階 B-tree 可以更有效地利用磁盤塊,減少磁盤 I/O 次數(shù)。
????????有序存儲(chǔ):B-tree 節(jié)點(diǎn)中的鍵值對(duì)按照索引字段的排序規(guī)則(升序或降序)排列,便于快速定位和范圍查詢。
? ? ? ? 2.1 為什么使用 B-Tree
????????B-Tree 和 B+Tree 都是樹形數(shù)據(jù)結(jié)構(gòu),用于在數(shù)據(jù)庫中存儲(chǔ)和查找數(shù)據(jù)。它們的主要區(qū)別在于數(shù)據(jù)的存儲(chǔ)方式和查找效率。
????????B-Tree 的每個(gè)節(jié)點(diǎn)都包含鍵和值,所有的鍵值對(duì)都存儲(chǔ)在樹的內(nèi)部節(jié)點(diǎn)和葉子節(jié)點(diǎn)中。這意味著一旦找到了正確的節(jié)點(diǎn),就可以立即獲取到對(duì)應(yīng)的值,無需進(jìn)一步的磁盤 I/O 操作。
????????而 B+Tree 只在葉子節(jié)點(diǎn)中存儲(chǔ)鍵值對(duì),內(nèi)部節(jié)點(diǎn)只存儲(chǔ)鍵。這意味著查找值時(shí),即使找到了正確的內(nèi)部節(jié)點(diǎn),還需要進(jìn)一步查找葉子節(jié)點(diǎn)才能獲取到值,可能需要額外的磁盤 I/O 操作。
三、執(zhí)行計(jì)劃
????????MongoDB執(zhí)行計(jì)劃(Execution Plan)是描述 MongoDB 如何執(zhí)行一條查詢語句的詳細(xì)過程和策略,它提供了關(guān)于查詢優(yōu)化器如何選擇索引、如何訪問數(shù)據(jù)、執(zhí)行成本估計(jì)等方面的詳細(xì)信息。通過分析執(zhí)行計(jì)劃,可以深入了解查詢性能、識(shí)別潛在的優(yōu)化點(diǎn)以及調(diào)試查詢性能問題。
? ? ? ? 執(zhí)行計(jì)劃語句
db.collection.find({field: value}).explain('verbosity')
????????使用?explain()
方法附加在查詢語句后面來獲取執(zhí)行計(jì)劃。explain()
接受一個(gè)可選的verbosity?
參數(shù),用來指定返回的執(zhí)行計(jì)劃詳細(xì)程度:????
-
queryPlanner
(默認(rèn)):提供查詢計(jì)劃的基本信息,包括查詢類型、候選索引、選定索引及其原因、查詢階段等。 -
executionStats
:除了查詢計(jì)劃基本信息外,還包括實(shí)際執(zhí)行時(shí)的統(tǒng)計(jì)信息,如掃描的文檔數(shù)、返回的文檔數(shù)、執(zhí)行時(shí)間、索引使用情況等。 -
allPlansExecution
:除了上述信息外,還會(huì)實(shí)際執(zhí)行所有候選索引并返回各自的執(zhí)行統(tǒng)計(jì),有助于對(duì)比不同索引的性能。
? ? ? ? 執(zhí)行計(jì)劃中需要重點(diǎn)關(guān)注:COLLSCAN、IXSCAN、keysExamined、docsExamined等關(guān)鍵字。
- COLLSCAN:代表該查詢進(jìn)行了全表掃描
- IXSCAN:代表進(jìn)行了索引掃描
- keysExamined:代表索引掃描條目
- docsExamined:代表文檔掃描條目
? ? ? ? 根據(jù)執(zhí)行計(jì)劃分析結(jié)果,可能要采取不同的優(yōu)化策略,比如:創(chuàng)建或調(diào)整索引、優(yōu)化查詢條件、使用覆蓋索引等。
????????綜上所述,MongoDB 執(zhí)行計(jì)劃提供了深入理解查詢執(zhí)行過程和優(yōu)化查詢性能的關(guān)鍵信息。通過解讀執(zhí)行計(jì)劃的各部分、對(duì)比不同計(jì)劃、分析統(tǒng)計(jì)信息,可以針對(duì)性地調(diào)整索引策略、優(yōu)化查詢語句或調(diào)整查詢選項(xiàng),從而提升查詢效率。結(jié)合使用相關(guān)工具和命令,可以實(shí)現(xiàn)對(duì)查詢性能的持續(xù)監(jiān)控和調(diào)優(yōu)。
往期經(jīng)典推薦:
全面解讀MongoDB高可用、高性能與高可擴(kuò)展架構(gòu)-CSDN博客
深入剖析MongoDB集群架構(gòu)設(shè)計(jì)-CSDN博客
TiDB存儲(chǔ)引擎TiKV揭秘-CSDN博客
揭開Spring Bean生命周期的神秘面紗-CSDN博客文章來源:http://www.zghlxwxcb.cn/news/detail-860334.html
決勝微服務(wù)架構(gòu):OpenFeign輕量級(jí)REST客戶端的魅力解析_feign配置loadbalancer-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-860334.html
到了這里,關(guān)于MongoDB 索引全攻略的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!