MySQL 8.0.12 InnoDB表碎片整理

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/vkingnew/article/details/82774987
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;的方式整理表的碎片,但是会锁表,在主从环境下会对从库有延迟。

猜你喜欢

转载自blog.csdn.net/vkingnew/article/details/82774987