MySQL 8.0.12 InnoDB表碎片整理
阿新 • • 發佈:2018-12-10
0.準備工作: 使用sysbench建立一個表,資料行數為1000萬行。 # ls -lh /data/mysql80/sbtest/sbtest1.ibd -rw-r----- 1 mysql mysql 2.7G Sep 12 14:44 /data/mysql80/sbtest/sbtest1.ibd 1.查詢碎片: SELECT t.TABLE_SCHEMA ,t.TABLE_NAME,t.ENGINE, t.TABLE_ROWS, CONCAT(ROUND(data_length/( 1024*1024*1024 ), 2), 'G') DATA, CONCAT(ROUND(index_length/( 1024*1024*1024 ), 2), 'G') IDX, CONCAT(ROUND(( data_length + index_length ) / ( 1024*1024*1024 ), 2), 'G') 'TOTAL SIZE', ROUND(index_length/data_length, 2) IX_FRAC, CONCAT(ROUND(( data_free/1024/1024),2), 'MB') AS data_free FROM information_schema.TABLES t WHERE t.TABLE_SCHEMA='sbtest' and t.table_name='sbtest1' ORDER BY data_length + index_length DESC; +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | TABLE_SCHEMA | TABLE_NAME | ENGINE | TABLE_ROWS | DATA | IDX | TOTAL SIZE | IX_FRAC | data_free | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | sbtest | sbtest1 | InnoDB | 9860480 | 2.46G | 0.15G | 2.60G | 0.06 | 3.00MB | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ 1 row in set (0.00 sec) 2.刪除資料和更新資料: 2.1 刪除100萬條記錄: mysql> delete from sbtest1 where id<=1000000; Query OK, 1000000 rows affected (23.62 sec) 2.2 檢視物理檔案: # ls -lh /data/mysql80/sbtest/sbtest1.ibd -rw-r----- 1 mysql mysql 2.7G Sep 19 17:19 /data/mysql80/sbtest/sbtest1.ibd 2.3 檢視邏輯檔案: +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | TABLE_SCHEMA | TABLE_NAME | ENGINE | TABLE_ROWS | DATA | IDX | TOTAL SIZE | IX_FRAC | data_free | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | sbtest | sbtest1 | InnoDB | 9860480 | 2.46G | 0.15G | 2.60G | 0.06 | 3.00MB | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ 1 row in set (0.00 sec) 3.更新資料: mysql> update sbtest1 set c='china' where id <3000000; Query OK, 1999999 rows affected (22.79 sec) Rows matched: 1999999 Changed: 1999999 Warnings: 0 3.1 物理檔案: # ls -lh /data/mysql80/sbtest/sbtest1.ibd -rw-r----- 1 mysql mysql 2.7G Sep 19 17:28 /data/mysql80/sbtest/sbtest1.ibd 3.2 邏輯檔案大小: +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | TABLE_SCHEMA | TABLE_NAME | ENGINE | TABLE_ROWS | DATA | IDX | TOTAL SIZE | IX_FRAC | data_free | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | sbtest | sbtest1 | InnoDB | 9860480 | 2.46G | 0.15G | 2.60G | 0.06 | 3.00MB | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ 1 row in set (0.01 sec) 可以看到更新資料和刪除資料後物理檔案大小和邏輯檔案的大小均沒有變化。 4.更新: mysql> optimize table sbtest1; or mysql> alter table sbtest1 engine=innodb; Query OK, 0 rows affected (36.58 sec) Records: 0 Duplicates: 0 Warnings: 0 # ls -lh /data/mysql80/sbtest/sbtest1.ibd -rw-r----- 1 mysql mysql 2.4G Sep 19 17:31 /data/mysql80/sbtest/sbtest1.ibd +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | TABLE_SCHEMA | TABLE_NAME | ENGINE | TABLE_ROWS | DATA | IDX | TOTAL SIZE | IX_FRAC | data_free | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | sbtest | sbtest1 | InnoDB | 9860480 | 2.46G | 0.15G | 2.60G | 0.06 | 3.00MB | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ 1 row in set (0.01 sec) 可以看到物理檔案變小了,但是邏輯查詢上還沒有變化。我們刪除300萬資料,表的行數還是接近1000萬。 mysql> optimize table sbtest1; +----------------+----------+----------+-------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +----------------+----------+----------+-------------------------------------------------------------------+ | sbtest.sbtest1 | optimize | note | Table does not support optimize, doing recreate + analyze instead | | sbtest.sbtest1 | optimize | status | OK | +----------------+----------+----------+-------------------------------------------------------------------+ 2 rows in set (27.73 sec) mysql> analyze table sbtest1; +----------------+---------+----------+----------+ | Table | Op | Msg_type | Msg_text | +----------------+---------+----------+----------+ | sbtest.sbtest1 | analyze | status | OK | +----------------+---------+----------+----------+ 1 row in set (0.04 sec) # ls -lh /data/mysql80/sbtest/sbtest1.ibd -rw-r----- 1 mysql mysql 2.4G Sep 19 17:36 /data/mysql80/sbtest/sbtest1.ibd --邏輯查詢: +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | TABLE_SCHEMA | TABLE_NAME | ENGINE | TABLE_ROWS | DATA | IDX | TOTAL SIZE | IX_FRAC | data_free | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ | sbtest | sbtest1 | InnoDB | 8874390 | 2.21G | 0.13G | 2.35G | 0.06 | 3.00MB | +--------------+------------+--------+------------+-------+-------+------------+---------+-----------+ 1 row in set (0.00 sec) 5.碎片的視覺化: https://github.com/jeremycole/innodb_ruby 總結: 推薦使用optimize table sbtest1; 加上analyze table sbtest1;的方式整理表的碎片,但是會鎖表,在主從環境下會對從庫有延遲。