MySQL的表碎片處理
一、表碎片的產生
對於mysql表資料,當你delete掉很多資料時,這些資料佔用的磁碟空間可能並不會立刻被回收;比如一張表有10G的資料,delete掉1G資料後,再檢視錶ibd檔案會發現檔案大小可能還是10G;如果這個表有insert操作的話,那麼mysql就會優先考慮能不能將新資料儲存到空白空間上,容易出現這樣的情況:某個空白空間的大小是2MB,新插入一條資料大小是1.5MB並儲存到該空白空間上,這時就會產生更小的空白空間,而這種更小的空白空間更難被利用,如果像這種碎片非常多,就會比較浪費資源而且降低表磁碟I/O效能。
對於頻繁地update操作,也很容易產生碎片問題。比如對於可變長欄位,如varchar、text、blob等欄位,如果update操作將資料大小改小,那麼也會產生碎片問題。
mysql目前比較常用的引擎是innodb和myisam,這兩種引擎下都有可能產生碎片,碎片的產生和消除都是隨機的,而碎片越多會給查詢掃描工作帶來越大的影響。
二、檢視錶碎片的方式
1、data_length+index_length與ibd檔案大小的比較
mysql5.5預設是共享表空間,從5.6開始預設是獨立表空間,每張表有自己的檔案空間。檢視方式就是看資料檔案大小和表資料量大小的差異:可以先在資料庫中通過系統表information_schema.tables或者“show table status like ‘tb’ ”語句計算出data_length+index_length的值,再到作業系統上檢視對應表的ibd檔案(或者myd、myi檔案)的物理大小。如果ibd檔案比data_length+index_length值大很多,說明表存在碎片。
例如檢視test庫下student表的碎片空間情況:
mysql> select table_name,(data_length+index_length)/1024/1024 length,engine,data_free
-> from information_schema.tables
-> where table_name=`student`;
+------------+-------------+--------+-----------+
| table_name | length | engine | data_free |
+------------+-------------+--------+-----------+
| student | 72.14062500 | InnoDB | 4194304 |
+------------+-------------+--------+-----------+
1 row in set (0.01 sec)
[root@cos7-jiang test]# ll -h student.ibd
-rw-rw----. 1 mysql mysql 76M Dec 12 13:53 student.ibd
根據系統表計算出student表資料為72MB,檢視ibd檔案大小為76MB,碎片空間大概有4MB左右,不算太多。
2、通過系統表tables的data_free欄位看錶碎片
mysql的系統表information_schema.tables中記錄著每張表的資料、索引大小,行數等重要資訊,主要欄位資訊如下:
table_schema:表所在資料庫名
table_name:表名
engine:表的儲存引擎
tables_rows:表資料行數
data_length:資料長度,即表資料大小,單位位元組
index_length:索引長度,即表索引大小,單位位元組
data_free:已分配但未使用的空間大小,單位位元組,可以認為是碎片空間
通過data_free欄位可以查出資料庫中有哪些表產生了碎片,data_length+index_length值就是表資料量總大小(拿這個求和值與表資料檔案大小比較,得到的差值往往與data_free值不一樣,不知道為什麼)。
可以用下面的SQL來統計資料庫中有哪些表產生了碎片空間:
mysql> select table_name,table_schema,engine,table_rows,data_length+index_length length,data_free
-> from information_schema.tables
-> where data_free !=0
-> and table_schema not in(`information_schema`,`mysql`,`performance_schema`);
+------------+--------------+--------+------------+----------+-----------+
| table_name | table_schema | engine | table_rows | length | data_free |
+------------+--------------+--------+------------+----------+-----------+
| student | test | InnoDB | 1075752 | 75644928 | 4194304 |
+------------+--------------+--------+------------+----------+-----------+
data_free值可以反映出表的碎片空間大小。上面student表data_free顯示4M,與上一個方式計算出的碎片大小近似吻合。
三、清理表碎片
一般通過optimize命令清理碎片,不過optimize命令對共享表空間不起作用。
對於mysql5.6,如果執行optimize table tb_name優化innodb表可能會報如下資訊:
mysql> optimize table jiang;
+------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+------------+----------+----------+-------------------------------------------------------------------+
| test.jiang | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| test.jiang | optimize | status | OK |
+------------+----------+----------+-------------------------------------------------------------------+
對於innodb表的優化,可以用alter table tb_name engine=innodb的形式優化,對於myisam表的優化可以直接使用optimize。
四、optimize操作介紹
mysql5.6的官方文件在13.7.2.4小節對optimize操作有詳細的介紹。optimize table命令的作用是重新組織表資料和關聯索引資料的物理儲存,以減小儲存空間並提高訪問表時的I/O效率;命令主要作用於innodb、myisam和archive引擎表,而命令對錶所做的實際更改取決於該表使用的儲存引擎。
·innodb引擎下的optimize操作
對於innodb表,optimize table操作實際對映為alter table … force操作,當對innodb表執行optimize操作時可能會出現下面的提示資訊:
mysql> optimize table jiang;
+------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+------------+----------+----------+-------------------------------------------------------------------+
| test.jiang | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| test.jiang | optimize | status | OK |
+------------+----------+----------+-------------------------------------------------------------------+
這實際上已經對錶做了優化,第一步是提示optimize操作不適用該型別表,第二步是對映為alter table操作執行併成功。
在mysql5.6.17之前,optimize操作沒有使用online DDL,因此整個操作期間會鎖表,表上不允許有DML操作;
從mysql5.6.17開始,對於常規的和分割槽的innodb表,optimize操作使用online DDL,這樣只會在操作的準備階段和提交階段鎖住DML操作,大大提高了併發性。
說明:
1、對於寫比較頻繁的表,容易產生碎片問題,但也不用經常進行清理,一般每週或者每月一次就可以了;
2、OPTIMIZE TABLE只對MyISAM,BDB和InnoDB表起作用,尤其是MyISAM表的作用最為明顯。此外,並不是所有表都需要進行碎片整理,一般只需要對包含可變長度的文字資料型別的表進行整理即可。
相關文章
- MySQL表碎片整理MySql
- MySQL分表後原分割槽表處理方案MySql
- web前端分享:效能最佳化之文件碎片處理Web前端
- mysql 1129處理MySql
- mysql 事務處理及表鎖定深入簡析MySql
- mysql,sqlserver資料庫單表資料過大的處理方式MySqlServer資料庫
- MySQL事務處理MySql
- MySQL 併發處理MySql
- 聊聊MySQL是如何處理排序的MySql排序
- PHP+MySQL 千萬級資料處理案例(二) 分表的意義PHPMySql
- 【問題處理】MySQL忘記root密碼的處理辦法MySql密碼
- Java 18 如何改進處理大型物件回收的記憶體碎片問題? -Java物件記憶體
- MySQL show processlist故障處理MySql
- Mysql如何處理死鎖MySql
- mysql之 OPTIMIZE TABLE整理碎片MySql
- Sqlserver的表沒有高水位但是有碎片的概念,sqlserver表的碎片的檢視和整理方法SQLServer
- openGauss 處理錯誤表
- php表單處理-143PHP
- Oracle資料表碎片整理Oracle
- 記一次 MySQL 資料庫單表恢復事故處理MySql資料庫
- MySQL資料庫INNODB表損壞修復處理過程分享MySql資料庫
- mysql分割槽表佔用大量容量處理(最佳化)及歸檔分割槽表MySql
- MySQL 處理重複資料MySql
- React 如何來處理表單React
- 分割槽表truncate慢處理
- Oracle資料庫表碎片整理Oracle資料庫
- Debezium zookeeper kafka mysql資料處理KafkaMySql
- Mysql自動處理同步報錯MySql
- mysql 5.7 執行緒阻塞處理MySql執行緒
- MySQL 動態字串處理詳解MySql字串
- MySQL:亂碼問題處理流程MySql
- windows 處理bat連線本地mysqlWindowsBATMySql
- MySQL碎片整理小節--例項演示MySql
- 如何處理 MySQL 萬用字元的模糊查詢MySql字元
- MySQL的事務處理及隔離級別MySql
- MySQL儲存過程的異常處理方法MySql儲存過程
- MySQL中不得不提的事務處理MySql
- Oracle 資料庫整理表碎片Oracle資料庫