1. 程式人生 > >InnoDB關鍵特性之change buffer

InnoDB關鍵特性之change buffer

dap 數據節點 排好序 適合 pre 成本 可能 like 命中

一、關於IOT:索引組織表

  表在存儲的時候按照主鍵排序進行存儲,同時在主鍵上建立一棵樹,這樣就形成了一個索引組織表,一個表的存儲方式以索引的方式來組織存儲的。

  所以,MySQL表一定要加上主鍵,通過主鍵來訪問MySQL表的性能是最好:

    1、顯式定義主鍵:primary key

    2、隱式定義主鍵:如果沒有指定主鍵,MySQL自己會默認建立一個主鍵(rowid隱藏主鍵)

1、特點

  1、表按照主鍵排好序,數據按照主鍵順序存放(核心原因)

  2、主鍵上有一棵樹,葉子節點就是數據節點

  3、表本身就是索引,表就是索引、索引就是表

  4、IOT對於通過主鍵找表數據的成本最低

2、IOT適合的場合

  1、根據主鍵訪問數據(永遠是效果最好的方式),一級索引

  2、主鍵選擇好,非常有利於insert,特別註意存在遞增列的情況

3、主鍵建立原則

  1、主鍵的順序最好和最常使用的索引列的順序一致

  2、如果能夠實現最常使用的索引列作為主鍵列,效果最好

    技巧:索引列+自增長列

4、IOT最大的弊端:所有主鍵以外的索引都是二級索引(innodb默認)

二、不訪問索引的其中一種情況

  索引成本比全表掃描的成本高,就算建了索引也不會走索引。

1、全表掃描的成本

  多塊讀,掃描冷數據,造成大量的物理讀。

  通過預讀機制,將可能要訪問的數據讀入內存,減少io訪問磁盤次數。

2、索引的成本

  1、訪問索引(內存命中的概率很高)

  2、主鍵的樹(內存命中的概率很高)

  3、集群因子(計算索引訪問成本):index clustering factor是oracle一個參數,是索引的有序度和主鍵的有序度的一個比較。

3、全表掃描優於索引情況

  查詢結果的記錄大於表中記錄一定比例(對於大多數數據庫來說,這個比例是10%)的時候,全表掃描要比使用索引快。

  這個主要是由於索引掃描後要利用索引中的指針去逐一訪問記錄,假設每個記錄都使用索引訪問,則讀取磁盤的次數是查詢包含的記錄數T,而如果表掃描則讀取磁盤的次數是存儲記錄的塊數B,如果T>B 的話索引就沒有優勢了。

  即先對結果數量估算,如果小於這個比例用索引,大於的話即直接全表掃描。

三、為什麽需要insert buffer,針對二級索引

1、索引數據頁的更新

  表的索引存於該表的ibd文件中,數據也存於此文件。表數據更新的同時也會更新對應的表的索引數據,所以:對表進行insert時,很可能會產生大量的物理讀(物理讀索引數據頁)

技術分享

2、索引對insert的影響

  1、表insert,對應表上的所有索引都需要insert;

  2、假設這些索引不常使用,容易產生物理讀;

  3、索引的順序和表的順序完全不一致;

  原則:一個表上的索引最好不超過6個

3、change buffer

  A special data structure that records changes to pages in secondary indexes. These values could result from SQL INSERT, UPDATE, or DELETE statements (DML). The set of features involving the change buffer is known collectively as change buffering, consisting of insert buffering, delete buffering, and purge buffering.

技術分享

  將對索引的更新記錄存入insert buffer中,而不是直接調入索引頁進行更新;擇機進行merge insert buffer的操作,將insert buffer中的記錄合並(merge)到真正的輔助索引中。

  解決了insert表數據產生過多物理讀的問題。

4、merge insert buffer的操作可能發生在什麽情況下

  在merge insert buffer之前,insert buffer數據是存在內存中,為了防止數據庫意外宕機導致數據丟失,系統會周期性將insert buffer數據寫入共享表空間中。

  1、輔助索引頁被讀取到buffer pool中

    例如這在執行正常的select查詢操作,索引頁被調入內存,該索引頁對應在insert buffer中的索引更改記錄就會發生merge操作。

  2、insert buffer bitmap頁追蹤到該輔助索引頁已無可用空間時

    存於ibd文件中(表數據文件)

    記錄每一個索引頁在insert buffer中對應的行數

  3、master thread工作

    在master thread線程中每秒或每10秒會進行一次merge insert buffer的操作,不同之處在於每次進行merge操作的頁的數量不同。

mysql> show engine innodb status\G
……
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
 insert 0, delete mark 0, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0

  1、insert buffer空間占有量:2*16K

    對表進行批量IDU的時候,可能會導致change buffer迅速增加。

  2、merges合並的次數:一次合並對應一次物理讀

  3、insert 0, delete mark 0, delete 0

  4、discarded是數據還沒有合並,索引被刪除,相應的數據也要被刪除。

假設:

  Merges:10

  Insert:1000

  Delete Mark:3000

  Delete:3000

  (1000+3000+3000)/10=700:表示merge一次解決了對索引的多少次更改,此處700次索引更改一次merge

5、如何看insert buffer的效果

  1、insert buffer所占空間,占比太高就影響緩沖性能

  2、每次merge處理的數據量

    1、merges如果很高,說明insert buffer調小了,也說明索引建多了;

    2、對表進行批量IDU的時候,可能會導致insert buffer迅速增加。

6、關註change buffer在innodb buffer pool中的占比

mysql> show variables like %change_buffer%;
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| innodb_change_buffer_max_size | 25    |
| innodb_change_buffering       | all   |
+-------------------------------+-------+
2 rows in set (0.01 sec)

  1、innodb_change_buffer_max_size:表示change buffer在buffer pool中的最大占比,默認25%,最大50%

  2、innodb_change_buffering:表示索引列merge對象,all表示對IDU索引列都起作用,都進行merge,如果只想對insert索引列進行merge,就把all改為inserts。

調整依據:

  1、如果系統中有嚴重的insert、update並且還有活躍的delete時,就增大max_size;

  2、針對不更改數據的純報表系統,可以減小該參數值。

InnoDB關鍵特性之change buffer