程序員寫了多年CRUD,總結出數據庫索引這幾點值得注意

索引,被稱之為數據庫的目錄,可以讓我們快速地找到對應的數據。但是,索引其實是一把雙刃劍,如果使用不合理,不僅查詢數據的速度不會變快,反而適得其反,讓查詢變慢。

工作原理

索引是對數據庫表中一列或多列的值進行排序的一種結構,使用索引可快速訪問數據庫表中的特定信息。使用索引,我們的目的就是要更快地查詢數據。可以說,索引的本質就是空間換時間。那麼,索引是如何工作的呢?


程序員寫了多年CRUD,總結出數據庫索引這幾點值得注意


我們以上圖為例,在數據庫中存著兩個字段,一個是主鍵ID,另外一個是字段K。當我們直接查詢主鍵的時候,可以在左邊的主鍵索引中直接找到對應的數據塊,然後從磁盤中將他們讀取出來,而當我們使用K字段進行查詢的時候,則先要從右邊的二級索引中,先找到對應的K有那些符合條件的主鍵,然後再去主鍵索引中讀取相關的數據塊的位置,再去磁盤中讀取出來。

索引必須作為頻繁查詢的條件

通俗易通的說,我們應該選擇WHERE後面的條件,而不是SELECT後面的元素。如果這個條件從來不做查詢條件,記錄了也沒有什麼意義。

舉個簡單的例子,你在開發一款快遞查詢系統。你想知道昨天從深圳發出的快遞有多少份,那麼你就應該建立一個發出時間,發出地址的快遞。假如你一個索引都沒建,那會發生什麼事情,需要掃描所有的快遞記錄,逐個進行比較,才能夠找到發出地點是深圳,發出時間是昨天的訂單。假如你只建了發出時間是昨天的索引,那麼就會掃描昨天的訂單,然後逐個比較是否發出點是深圳,然後選擇對應的結果。同理,如果你只建了發出地點的索引,那數據庫就會幫你找到所有的深圳的訂單,然後找到發出時間是昨天的。所以,最好的辦法,是建立時間跟發出地點的聯合索引。

一般來說,索引使用的都是最左前綴原則。這與我們索引的存儲格式息息相關,我們的索引,一般都使用的是多叉排序樹。舉個例子,如果我們有4個字段都可能作為查詢條件,假如我們建立的聯合索引為(1,2,3,4),那麼當我們的查詢條件為(1)(1,2)(1,2,3)都是可以命中索引的。假如我們的查詢條件是(1,2,4)那麼也可以命中索引,不過只會使用(1,2),4需要回表都數據後才能得到結果。假如我們的查詢字段是(2,3,4),那麼很抱歉,我們沒辦法使用到這個索引。

程序員寫了多年CRUD,總結出數據庫索引這幾點值得注意

索引最好具有唯一性

索引的數據列,當然是越特殊越好,最好是能夠讓數據庫的查詢下降幾個量級的。我們舉個例子,假如我們開發的是一款全國大學生統一管理軟件。假如數據庫中有2千萬大學生。現在我們想查詢籍貫為湖北的男大學生,我們該如何使用索引呢?假如我們使用性別作為數據庫索引,由於性別只有男女,所以即使命中了性別索引,掃描的數據量也是千萬級別的。所以,我們應該使用更特殊的字段籍貫去作為索引,可以減少更多的數據掃描量。

但是凡是無絕對,並不是說唯一性不高的的數據我們就不建立索引。在前面我們已經降到索引的工作流程,先在索引上找到對應的主鍵,然後再回表查詢數據。還是上述的例子,假如我們的請求總是查詢某個城市某個省份的男生/女生數量,那麼,我們最好的辦法是建立一個城市/性別的聯合索引,這樣子我們可以在索引上就能計算出最終的數據量,進而不用回表查詢,提升查詢的效率。這種方法,我們稱之為索引覆蓋,就是讓查詢的條件,查詢的內容儘量在索引上,從而減少回表,提升效率。


程序員寫了多年CRUD,總結出數據庫索引這幾點值得注意


索引數據不能頻繁變更

在B+樹索引中,索引其實是一顆多叉排序樹,所以,每當索引數據變更的時候,就會調整數據。調整數據是需要代價的,假如被索引數據頻繁變更的時候,將會大大影響插入的性能。舉個例子,在電商系統中,我們常常有這樣的場景,展示有貨的商品。那麼,我們可否以剩餘庫存的數量作為索引呢?最好不要,因為庫存的變更是非常頻繁的,如果使用庫存數量作為索引,每次都要進行索引的調整,而庫存系統的寫入本來就是瓶頸之一,無疑是雪上加霜。

最後

還有很多需要注意或者優化地項沒辦法一一說出來,大家可以多交流,多積累經驗。歡迎大家關注我,共同學習,共同進步。大家的支持是我繼續嘮嗑的動力。同名公眾號(沙茶敏碎碎念)


分享到:


相關文章: