普通索引和唯一索引,應該怎么選擇?


如果業務能保證唯一性的情況下,還是選擇普通索引性能更好

select id from T where k=5

首先,我們看下

查詢過程

對於普通索引來說,查詢到滿足條件的第一個記錄后,需要查找下一個記錄,直到碰到第一個不滿足k=5條件的記錄

對於唯一索引來說,由於索引上有唯一性,查詢到第一個滿足條件的記錄后就停止檢索了

所以在這里的區別就是普通索引會多查那么一下,那么這兩種的性能差別有多大呢?

答案是微乎其微,為甚呢?

因為mysql在讀數據的時候,比如說上面那條語句,如果沒有在內存中,會去磁盤中把k=5這條數據所在的整個數據頁都讀入內存中,在innodb中,每個數據頁的大小默認是16KB,因為引擎是按頁讀寫的,所以說,當找到k=5的記錄的時候,它所在的數據頁都在內存里了,那么對於普通索引來說,要多做的那一次查詢的操作,就只需要一次指針尋找和一次計算,當然,如果K=5這個記錄剛好是這個數據頁的最后一個記錄,那么要取下一個記錄,必須讀取下一個數據頁,這個操作會稍微復雜一些,但是對於整形字段,一個數據頁可以放近千個key,因此出現這種情況的概率會很低,所以,我們計算平均性能差異時,扔可以認為這個操作成本對於現在的cpu來說可以忽略不計。

更新過程

首先我們說下change_buffer的概念,如果要更新的數據在內存中,那么就直接更新內存,如果要更新的數據沒有在內存中,那么就會把更新記錄存在change_buffer中,等到有查詢來讀取數據頁的時候,就會執行change_buffe中有關這個數據頁的操作。通過這種方式就能保證這個數據邏輯的正確性。

change_buffer也會持久化到磁盤,將change_buffer中的操作應用到原數據頁,得到最新結果的過程稱為merge,除了訪問這個數據頁會觸發merge外,系統有后台線程會定期merge,在數據庫正常關閉的過程中,也會執行merge

顯然如果能夠將更新操作記錄在change_buffer,減少讀磁盤,語句的執行速度會得到明顯的提升。而且,數據讀入內存是需要占用buffer pool的,所以這種方式還能夠避免占用內存,提高內存利用率

那么什么條件下可以使用changebuffer呢?

對於唯一索引來說,每次更新都必須先判斷這個操作是否違反唯一性約束,比如,要插入(4,400)這個記錄,就要先判斷現在表中是否存在這個記錄,而這必須要將數據頁讀入內存才能判斷,既然都讀入內存了,那么直接更新內存會更快,就沒必要使用change buffer了。

因此,唯一索引的更新就不能使用change buffer

change buffer用的是buffer pool里的內存,因為不能無限增大,change buffer的大小,可以通過參數innodb_change_buffer_max_size來動態設置,這個參數設置為50的時候,表示change buffer的大小最多只能占用buffer pool的50%

現在我們看下如果要在這張表中插入一個新記錄(4,400)的話,innodb的處理流程是什么樣的

第一種情況是,這個記錄要更新的目標頁在內存中,這時,innodb的處理流程如下:

  • 對於唯一索引來說,找到3和5之間的位置,判斷到沒有沖突,插入這個值,語句執行結束
  • 對於普通索引來說,找到3和5的位置,插入這個值,語句執行結束

這樣看來,普通索引和唯一索引對更新語句性能影響的差別,只是一個判斷,只會耗費微小的CPU時間。

但,這不是我們關注的重點

第二中情況是,這個記錄要更新的目標頁不在內存中,這時,流程如下:

  • 對於唯一索引來說,由於需要判斷唯一性,所以要從磁盤中讀取所在的數據頁到內存中,判斷到沒有沖突,插入值,結束
  • 對於普通索引來說,則是將更新記錄在change buffer,結束

將數據從磁盤讀入內存涉及隨機io的訪問,是數據庫里面成本最高的操作之一。changebuffer因為減少了隨機磁盤訪問,所以對更新性能的提升是會很明顯的

但是change buffer的應用場景只是對於寫多讀少的的業務,頁面在寫完以后馬上被訪問的概率比較小,此時changebuffer的使用效果最好,這種業務模型常見的就是賬單類,日志類的系統。

反過來,如果一個業務的更新模式是寫完之后馬上會做查詢,那么即使滿足了條件,將更新記錄在change buffer,但之后由於馬上要訪問這個數據頁,會立即觸發Merge過程,這樣隨機訪問io的次數不會減少,反而增加了change buffer的維護代價。所以,對於這種業務模式來說,change buffer反而起到了反作用。

所以,如果所有的更新后面,都馬上伴隨着對這個記錄的查詢,那么你應該關閉change buffer,而在其他情況下,change buffer都能提升更新性能。

小結

如果業務能保證一個字段的唯一性並且針對的是寫多多少的業務模式,那么還是選擇普通索引的好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM