一、原因:
- 非聚簇索引存儲了對主鍵的引用,如果 select 字段不在非聚簇索引內,就需要跳到主鍵索引。
- 如果非聚簇索引值重復率高,那么查詢時就會大量出現上圖中從右邊跳到左邊的情況,導致整個流程很慢
原因就是上面的。
數據庫中聚集索引只有一個,默認主鍵。其他用戶創建的索引都是非聚集索引。
非聚集索引存儲了對主鍵的引用,即通過索引確定葉子節點之后,還需要再次根據主鍵去查詢數據。(所以會查詢兩次)
如果非聚集索引重復率高(即一個同樣的值有多個主鍵),那么首先你會從索引中取一半主鍵值,然后根據主鍵值再去查詢數據,增加了IO,所以特別耗時。
大概就是上面的原因。
二、聚集索引和非聚集索引
2.1 區別:
主要可以參考高性能MySQL。這里簡單總結一下
- 聚集索引把索引和數據存在了一起。
可以這么理解,聚集索引的葉子節點存儲的是數據的指針(或者是數據本身)。具體暫時不確定,后續了解之后再確定。
- 非聚集索引(也叫二級索引)的葉子節點存儲的是主鍵值(或叫做聚集索引值)
2.2 查詢次數
非聚集索引需要兩次查找,先從非聚集索引中找到主鍵值,然后再去聚集索引中找到具體數據。
聚集索引只需要查找本身。
2.3 為什么不適合在枚舉少的字段上建立索引?
如果聚集索引唯一,那么條件只會確定幾條值的主鍵,然后去聚集索引中查詢還可以。
如果聚集索引重復,那么條件會確定近乎一般或者1/3或者1/5的主鍵值,然后再一個一個去聚集索引中查詢,就會引起問題。
2.4 如果沒有索引,數據庫是怎么查詢的?
全表掃描。
如果索引可以減少全表掃描,那么索引有效。如果索引導致了比全表掃描更糟糕的結果,那么還不如全表掃描。
三、參考
1. 為什么重復值高的字段不能建索引(比如性別字段等) - 扯 - 博客園
注:說的很精簡。
2. 從性別字段不適合建索引說起 - Win32FanEx 的專欄 - CSDN 博客
注:詳細講解了實例,挺好的,便於理解。
3. 為什么狀態少的字段不能建索引 - youzhouliu 的博客 - CSDN 博客
注:創建10W數據,親自操作和分析,挺好的。
4. 聚集索引和非聚集索引(整理) - 布顏書 - 博客園
注:這個還需理解。如果不理解聚集索引和非聚集索引,就無法解決這個問題。
這篇教程特別好。