普通索引 唯一索引 區別

2021-10-23 09:20:39 字數 2430 閱讀 8076

分析唯一索引和普通索引在查詢語句和更新語句中的效能影響。

假設執行以下語句

select id from t where k=

5

這個查詢語句在索引樹上查詢的過程,先是通過 b+ 樹從樹根開始,按層搜尋到葉子節點,然後可以在資料頁內部通過二分法來定位記錄。

以上看起來唯一索引比普通索引少了一步判斷,其實帶來的效能差距微乎其微,因為innodb 的資料是按資料頁為單位來讀寫的。也就是說,當需要讀一條記錄的時候,並不是將這個記錄本身從磁碟讀出來,而是以頁為單位,將其整體讀入記憶體。因為引擎是按頁讀寫的(在 innodb 中,每個資料頁的大小預設是 16kb),所以說,當找到 k=5 的記錄的時候,它所在的資料頁就都在記憶體裡了。那麼,對於普通索引來說,要多做的那一次「查詢和判斷下一條記錄」的操作,就只需要一次指標尋找和一次計算。所以效能差距並不是很大。

change buffer

更新過程會涉及到乙個重要的概念 change buffer。

當需要更新乙個資料頁時,如果資料頁在記憶體中就直接更新,而如果這個資料頁還沒有在記憶體中的話,在不影響資料一致性的前提下,innodb 會將這些更新操作快取在 change buffer 中,這樣就不需要從磁碟中讀入這個資料頁了。在下次查詢需要訪問這個資料頁的時候,將資料頁讀入記憶體,然後執行 change buffer 中與這個頁有關的操作。

將 change buffer 中的操作應用到原資料頁,得到最新結果的過程稱為 merge。除了訪問這個資料頁會觸發 merge 外,系統有後台執行緒會定期 merge。在資料庫正常關閉(shutdown)的過程中,也會執行 merge 操作

如果能夠將更新操作先記錄在 change buffer,減少讀磁碟,語句的執行速度會得到明顯的提公升。而且,資料讀入記憶體是需要占用 buffer pool 的,所以這種方式還能夠避免占用記憶體,提高記憶體利用率。

change buffer 的使用情形

對於唯一索引來說,所有的更新操作都要先判斷這個操作是否違反唯一性約束。比如插入 (4,400) 這個記錄,就要先判斷現在表中是否已經存在 k=4 的記錄,而這必須要將資料頁讀入記憶體才能判斷。如果都已經讀入到記憶體了,那直接更新記憶體會更快,就沒必要使用 change buffer 了。

假設在這張表中插入乙個新記錄 (4,400) 的話

第二種情況是,這個記錄要更新的目標頁不在記憶體中

將資料從磁碟讀入記憶體涉及隨機 io 的訪問,是資料庫裡面成本最高的操作之一。change buffer 減少了隨機磁碟訪問,所以對更新效能的提公升是會很明顯的

merge 的時候是真正進行資料更新的時刻,而 change buffer 的主要目的就是將記錄的變更動作快取下來,所以在乙個資料頁做 merge 之前,change buffer 記錄的變更越多(也就是這個頁面上要更新的次數越多),收益就越大。因此,對於寫多讀少的業務來說,頁面在寫完以後馬上被訪問到的概率比較小,此時 change buffer 的使用效果最好。這種業務模型常見的就是賬單類、日誌類的系統。

假設我們要在表上執行這個插入語句

mysql>

insert

into t(id,k)

values

(id1,k1)

,(id2,k2)

;

我們假設當前 k 索引樹的狀態,查詢到位置後,k1 所在的資料頁在記憶體 (innodb buffer pool) 中,k2 所在的資料頁不在記憶體中。

這條更新語句做了如下的操作

page 1 在記憶體中,直接更新記憶體;

page 2 沒有在記憶體中,就在記憶體的 change buffer 區域,記錄下「我要往 page 2 插入一行」這個資訊

將上述兩個動作記入 redo log 中(3 和 4)。

做完以上動作,乙個事務就完成了,可以看出執行這條更新語句的成本很低,就是寫了兩處記憶體,然後寫了一處磁碟(兩次操作合在一起寫了一次磁碟),而且還是順序寫的。(其餘的是後台操作)

那之後的讀請求會怎樣呢?

假如執行select * from t where k in (k1, k2)

讀 page 1 的時候,直接從記憶體返回。

要讀 page 2 的時候,需要把 page 2 從磁碟讀入記憶體中,然後應用 change buffer 裡面的操作日誌,生成乙個正確的版本並返回結果

redo log 主要節省的是隨機寫磁碟的 io 消耗**成順序寫),而 change buffer 主要節省的則是隨機讀磁碟的 io 消耗。

普通索引唯一索引的區別

1 查詢 唯一索引查到滿足條件的資料後直接返回 普通索引查到滿足條件的資料後會繼續匹配下一行是否滿足條件 2 寫唯一索引 需要判斷是否重複,需要將對應的頁從磁碟載入的記憶體中 普通索引 普通索引使用change buffer 占用buffer pool的空間 直接將更新寫入到buffer中,不用讀盤...

主索引 普通索引 候選索引 唯一索引

1.普通索引 普通索引 由關鍵字key或index定義的索引 唯一的任務是加快對資料的訪問速度。因此,應該只為那些最經常出現在查詢條件 wherecolumn 或排序條件 orderbycolumn 中的資料列建立索引 2.唯一索引 在某個資料列只包含彼此不同的值,在為這個資料列建立索引時就應該用關...

普通索引 唯一索引 主鍵索引 候選索引

1 普通索引 1 定義 最基本的索引型別,沒有唯一性之類的限制。2 建立方式 a 建立索引,例如create index 索引的名字 on tablename 列的列表 b 修改表,例如alter table tablename add index 索引的名字 列的列表 c 建立表的時候指定索引,例...