day1
1. MySQL的索引類型有哪些?
MySQL里的索引就像是書的目錄,能幫數據庫快速找到你要的數據。以下是各種索引類型的通俗解釋:
按數據結構分
- B+樹索引:最常用的一種,數據像在一棵樹上分層存放,能快速定位范圍數據,比如查找某個分數區間內的學生成績。
- 哈希索引:通過把數據變成哈希值來建立索引,查找速度特別快,但只適合精確查找,比如根據身份證號找特定的人,要是找某個范圍的就不行了。
- 倒排索引(全文索引):主要用來處理文本數據,比如在一篇文章里找特定的詞,它會記錄每個詞在哪些文檔里出現過。
- R - 樹索引:用于處理多維空間數據,比如地圖上查找某個區域內的所有店鋪。
基于InnoDB B+樹索引分
- 聚簇索引:數據和索引是放在一起的,就像書的正文和目錄裝訂在一起,一般主鍵會默認是聚簇索引,找數據時速度快。
- 非聚簇索引:數據和索引分開存放,就像書的正文和目錄分開,查找到索引后還得再去查數據。
按索引性質分
- 普通索引:最基本的索引,用來加快查詢速度,比如在學生表中給姓名字段建普通索引,查特定姓名的學生更快。
- 主鍵索引:特殊的唯一索引,每個表只能有一個,就像每個人的身份證號,不能重復且必須有,用來唯一標識一行數據。
- 聯合索引:把多個字段組合起來建索引,比如在學生表中把班級和成績兩個字段建聯合索引,查某個班級特定成績范圍的學生時會更高效。
- 唯一索引:保證索引列的值不能重復,但可以有NULL值,比如員工表中員工編號字段建唯一索引。
- 全文索引:上面按數據結構分的時候講過,用于在文本中快速查找特定詞匯。
- 空間索引:和R - 樹索引類似,用于處理地理空間等數據,比如查找某個城市內的所有加油站。
2.MySQLInnoDB 引擎中的聚簇索引和非聚簇索引有什么區別?
聚簇索引
- “索引葉子結點存儲的是數據行,可以直接訪問完整數據”:就好比一本書,它的目錄后面直接跟著對應的正文內容。在聚簇索引里,索引的最底層(葉子結點)存的不只是索引信息,而是整行的數據。所以當你通過聚簇索引去查找數據時,一下子就能拿到完整的一行數據,不用再去別的地方找。
- “每個表只能有一個聚簇索引,通常是主鍵索引,適合范圍查詢和排序”:每個表就像一本獨特的書,只能有一份這種目錄和正文緊密相連的結構,也就是只能有一個聚簇索引。一般情況下,主鍵就充當了這個聚簇索引,因為主鍵能唯一確定一行數據。如果要查找某個范圍的數據,比如找成績在80 - 90分之間的學生記錄,或者要對數據進行排序,聚簇索引處理起來就比較高效,因為數據在物理存儲上是按照一定順序排列的。
非聚簇索引
- “索引葉子節點存儲的是數據行的主鍵和對應的索引列,需通過主鍵才能訪問完整的數據行”:非聚簇索引像是另外單獨的一個小目錄,這個小目錄里記錄的是數據行的主鍵信息以及對應的索引列信息。當你通過這個小目錄找到對應的主鍵后,還得再去聚簇索引那里,根據主鍵把完整的數據行找出來,就好像你先在小目錄里查到頁碼,還得去書的正文里找具體內容。
- “一個表可以有多個非聚簇索引(稱之為非主鍵索引、輔助索引、二級索引),適用于快速查找特定列的數據”:一個表可以有很多個這樣的小目錄,也就是可以有多個非聚簇索引。當你只需要查找表中的某一個或幾個特定列的數據時,用非聚簇索引就比較快。比如你只想查學生表中的學生姓名,在姓名字段上建了非聚簇索引的話,就能快速定位到這些姓名信息。
3. MySQL 的存儲引擎有哪些?它們之間有什么區別?
InnoDB
- 支持事務、行級鎖和外鍵:事務就像一個打包任務,要么全成功,要么全失敗,比如轉賬時同時增減雙方賬戶金額。行級鎖是只鎖定要處理的那一行數據,這樣別人還能操作其他行,就像你在圖書館占一個座位,不妨礙別人坐其他座位。外鍵能把不同表的數據關聯起來,比如學生表和成績表通過學號關聯。
- 提供高并發性能,適用于高負載的OLTP應用:可以同時處理很多人的操作請求,像銀行系統很多人同時轉賬、查詢等。
- 數據以聚集索引的方式存儲,提高檢索效率:數據存放方式讓查找速度變快,就像書的目錄和正文放一起,找內容方便。
MyISAM
- 不支持事務和外鍵,使用表級鎖:沒有事務打包功能,也不能關聯不同表數據。表級鎖是鎖定整張表,就像你把整個圖書館占了,別人都不能用。
- 適合讀取多、更新少的場景,如數據倉庫:如果只是經常查數據,很少改數據,用它就挺好,像公司用來分析歷史數據的數據倉庫。
- 具有較高的讀性能和較快的表級鎖定:讀數據速度快,鎖定表也快。
MEMORY
- 數據存儲在內存中,速度快,但數據在服務器重啟后丟失:數據放在內存里,訪問就像在眼前拿東西一樣快。不過服務器一重啟,內存里的數據就沒了,就像電腦重啟后沒保存的臨時文件沒了。
- 適用于臨時數據存儲或快速緩存:比如存臨時計算結果,或者做快速緩存來加快訪問。
NDB (NDCluster)
- 支持高可用性和數據分布,適合大規模分布式應用:能保證服務一直可用,數據還能分散存,適合像大型電商平臺那種大規模分布式系統。
- 提供行級鎖和自動分區:行級鎖不影響別人操作其他行,自動分區把數據分到不同地方存,提高性能。
ARCHIVE
- 用于存儲大量歷史數據,支持高效的插入和壓縮:適合存公司多年的歷史訂單等大量歷史數據,存數據快還能壓縮節省空間。
- 不支持索引,適合日志數據存儲:不能用索引快速查找,但存日志數據很合適,反正日志主要是按順序記錄。
day2
1.MySQL 索引的最左前綴匹配原則是什么?
把 MySQL 索引想象成一本字典。字典前面有個目錄,我們可以快速找到想要的字,MySQL 索引就和這目錄類似,能幫數據庫快速找到數據。最左前綴匹配原則,就像是查字典時按照順序查一樣。
聯合索引就像多層目錄
在 MySQL 里,如果我們給多個字段創建了聯合索引,這就好比字典有個多層的目錄。比如說,我們給一個表的姓、名這兩個字段建了聯合索引,這個聯合索引就像是字典先按姓排了個順序,在每個姓下面又按名排了順序。
必須從最左邊開始查找
最左前綴匹配原則要求我們查詢的時候得從聯合索引的最左邊字段開始用。還拿姓和名的聯合索引來說,如果我們只根據“名”去查,這個聯合索引就幫不上忙了,因為索引是先按姓排的。只有先根據“姓”查,然后可能再根據“名”進一步縮小范圍,索引才能發揮作用。
連續使用索引字段
再舉個例子,如果聯合索引是 (字段A, 字段B, 字段C) 。當我們查詢條件是 “字段A = 某個值” 時,索引能用;當查詢條件是 “字段A = 某個值 AND 字段B = 某個值” 時,索引也能用;當查詢條件是 “字段A = 某個值 AND 字段B = 某個值 AND 字段C = 某個值” 時,索引還是能用。但要是查詢條件是 “字段B = 某個值 AND 字段C = 某個值” ,沒有最左邊的字段A,索引就用不上了。而且查詢時字段得連續用,要是查詢條件是 “字段A = 某個值 AND 字段C = 某個值” ,跳過了字段B,那么索引也只能用到字段A,字段C那部分索引就不能用。
簡單來說,最左前綴匹配原則就是在使用聯合索引查詢時,要從最左邊的字段開始,按照順序連續使用索引里的字段,這樣索引才能高效地幫我們找到數據。
2.為什么 MySQL選擇使用 B+樹作為索引結構?
可以把 MySQL 里的數據想象成圖書館里的大量書籍,而索引就像是圖書館的目錄,能讓我們快速找到想要的書。MySQL 選擇 B+樹作為索引結構,主要有下面幾個原因:
1. 查找效率高
B+樹有個特點,它的所有數據都存放在葉子節點,而且葉子節點之間有指針相連,形成了一個有序鏈表。這就好比圖書館的目錄,把同一類書按照編號排得整整齊齊。當我們要查找某條數據時,就像在目錄里找對應的書編號,通過一層一層地比較節點上的值,能快速縮小查找范圍,找到我們想要的數據。而且不管數據量有多大,查找的時間都比較穩定,不會因為數據變多就慢很多。
2. 適合范圍查詢
在實際應用中,我們經常需要查詢某個范圍內的數據,比如查詢年齡在 20 到 30 歲之間的用戶。B+樹的葉子節點是有序的鏈表,這就方便極了。我們只要找到范圍的起始點,然后順著鏈表往后找,就能把這個范圍內的數據都找出來。就像在圖書館目錄里找到某一類書的起始編號,然后順著編號順序就能找到這一類里所有的書。
3. 磁盤讀寫性能好
數據庫的數據通常存放在磁盤上,磁盤讀寫是比較耗時的操作。B+樹的節點可以存儲多個鍵值對,每個節點對應磁盤上的一個頁。這樣一來,一次磁盤讀取能獲取更多的數據,減少了磁盤 I/O 的次數。就好比我們去圖書館借書,一次能多拿幾本,就不用來回跑那么多次了,效率自然就提高了。
4. 插入和刪除操作穩定
在數據庫里,數據是經常要進行插入和刪除操作的。B+樹在進行這些操作時,能通過節點的分裂和合并來保持樹的平衡,不會因為頻繁的插入和刪除導致樹的結構變得很混亂,影響查找效率。這就像圖書館的管理員,在不斷地添加和拿走書籍后,還能把書架整理得井井有條,讓我們還是能快速找到想要的書。
總的來說,B+樹的這些優點讓它很適合作為 MySQL 的索引結構,能讓數據庫在查找、插入、刪除等操作上都有比較好的性能表現。
3.MySQL 三層 B+樹能存多少數據?
要估算 MySQL 三層 B+ 樹能存多少數據,我們需要先了解 B+ 樹的結構特點,再分析每個節點大概能存儲多少數據,最后得出三層 B+ 樹的總存儲量。
B+ 樹結構基礎
B+ 樹是一種多路平衡查找樹,在 MySQL 里,B+ 樹的非葉子節點(索引節點)只存儲索引信息,而數據都存放在葉子節點中。葉子節點之間通過指針相連,形成有序鏈表。我們可以把 B+ 樹想象成一個多層的目錄結構,非葉子節點是上層目錄,葉子節點是最終存放具體內容的頁面。
計算各層節點可存儲的數據量
1. 假設前提
- 一個數據頁的大小通常為 16KB(這是 MySQL InnoDB 存儲引擎默認的數據頁大小)。
- 非葉子節點(索引節點)主要存儲索引鍵值和指向子節點的指針。假設一個索引鍵值和指針的組合大小為 8 字節(這只是為了方便計算做的假設,實際大小會因數據類型等因素而不同)。
- 葉子節點存儲實際的數據記錄,假設一條數據記錄大小為 1KB(同樣是假設值,實際大小取決于表結構)。
2. 計算非葉子節點可存儲的子節點指針數量
由于一個數據頁大小是 16KB(即 16 * 1024 = 16384 字節),一個索引鍵值和指針組合大小為 8 字節,那么一個非葉子節點能存儲的子節點指針數量為:16384 ÷ 8 = 2048 個。
3. 分析三層 B+ 樹的存儲情況
- 第一層(根節點):根節點是一個非葉子節點,它能存儲 2048 個指向第二層節點的指針。
- 第二層(中間層非葉子節點):每個第二層的非葉子節點同樣能存儲 2048 個指向第三層節點的指針。因為根節點有 2048 個指針指向第二層節點,所以第二層總共有 2048 個非葉子節點,那么第二層所有節點能指向的第三層節點數量為 2048 × 2048 個。
- 第三層(葉子節點):每個葉子節點存儲實際的數據記錄,假設一條記錄大小為 1KB,一個葉子節點(數據頁)能存儲 16 條記錄(16KB ÷ 1KB = 16)。由于第二層節點指向第三層的葉子節點數量為 2048 × 2048 個,所以三層 B+ 樹能存儲的數據記錄總數為 2048 × 2048 × 16 = 67108864 條。
需要注意的是,以上計算是基于假設的數據頁大小、索引鍵值和指針大小以及數據記錄大小得出的,實際情況中這些值會因表結構、數據類型等因素而有所不同,但通過這種方式能讓你大致了解三層 B+ 樹的存儲量級。