普通索引和唯一索引,傻傻分不清楚?
兩種索引對查詢語句和更新語句的性能影響來進行分析
查詢過程
假設,執行查詢的語句是 select id from T where k=5。這個查詢語句在索引樹上查找的過 程,先是通過 B+ 樹從樹根開始,按層搜索到葉子節點,也就是圖中右下角的這個數據頁,然后 可以認為數據頁內部通過二分法來定位記錄。 對于普通索引來說,查找到滿足條件的第一個記錄 (5,500) 后,需要查找下一個記錄,直到 碰到第一個不滿足 k=5 條件的記錄。 對于唯一索引來說,由于索引定義了唯一性,查找到第一個滿足條件的記錄后,就會停止繼 續檢索。
那么,這個不同帶來的性能差距會有多少呢?答案是,微乎其微。
更新過程
在說之前,先引入一個新的東東,change buffer。何為change buffer???
當需要更新一個數據頁時,如果數據頁在內存中就直接更新,而如果這個數據頁還沒有在內存中 的話,在不影響數據一致性的前提下,InooDB 會將這些更新操作緩存在 change buffer 中, 這樣就不需要從磁盤中讀入這個數據頁了。在下次查詢需要訪問這個數據頁的時候,將數據頁讀 入內存,然后執行 change buffer 中與這個頁有關的操作。通過這種方式就能保證這個數據邏 輯的正確性。
它存在的意義就是能夠減少對硬盤IO的操作,我先保存著更新操作,等你要查,我才拿到緩存中更新,再給你呈現。懂了嗎?
回到更新操作。。。
對于唯一索引來說,所有的更新操作都要先判斷這個操作是否違反唯一性約束。比如,要插入 (4,400) 這個記錄,就要先判斷現在表中是否已經存在 k=4 的記錄,而這必須要將數據頁讀入內 存才能判斷。如果都已經讀入到內存了,那直接更新內存會更快,就沒必要使用 change buffer 了。 因此,唯一索引的更新就不能使用 change buffer,實際上也只有普通索引可以使用。
你看接下來這倆種情況你就會恍然大悟
第一種情況是,這個記錄要更新的目標頁在內存中。這時,InnoDB 的處理流程如下:
- 對于唯一索引來說,找到 3 和 5 之間的位置,判斷到沒有沖突,插入這個值,語句執行結 束;
- 對于普通索引來說,找到 3 和 5 之間的位置,插入這個值,語句執行結束。
這樣看來,普通索引和唯一索引對更新語句性能影響的差別,只是一個判斷,只會耗費微小的 CPU 時間。
但,這不是我們關注的重點。
第二種情況是,這個記錄要更新的目標頁不在內存中。這時,InnoDB 的處理流程如下:
- 對于唯一索引來說,需要將數據頁讀入內存,判斷到沒有沖突,插入這個值,語句執行結 束;
- 對于普通索引來說,則是將更新記錄在 change buffer,語句執行就結束了。
?
由于唯一索引用不上 change buffer 的優化機制,因此如果業務可以接受,從性能角度出發我 建議你優先考慮非唯一索引。
總結
以上是生活随笔為你收集整理的普通索引和唯一索引,傻傻分不清楚?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全字段排序 VS rowid 排序
- 下一篇: RC隔离级别下的GAP间隙锁