淺析MySQL數據碎片的產生(data free)

淺析MySQL數據碎片的產生

2011-03-30 09:28 核子可樂譯 51CTO 字號:T | T
一鍵收藏,隨時查看,分享好友!

MySQL列表,包括MyISAM和InnoDB這兩種最多見的類型,而根據經驗來講,其碎片的產生及消除都是隨機的。碎片會在你的表格中留下明顯的空白,而這會給列表掃描工做帶來至關大的困擾。對你的列表進行優化,這樣會使列表的全面及分區掃描工做進行得更有效率。php

AD:51CTO 網+首屆APP創新評選大賽火熱啓動——超百萬資源等你拿!mysql

【51CTO獨家譯文】本文淺析MySQL數據碎片的產生:定義,時間及成因。sql

MySQL列表,包括MyISAMInnoDB這兩種最多見的類型,而根據經驗來講,其碎片的產生及消除都是隨機的。碎片會在你的表格中留下明顯的空白,而這會給列表掃描工做帶來至關大的困擾。對你的列表進行優化,這樣會使列表的全面及分區掃描工做進行得更有效率。數據庫

碎片——實例session

MySQL具備至關多不一樣種類的存儲引擎來實現列表中的數據存儲功能。 每當MySQL從你的列表中刪除了一行內容,該段空間就會被留空。而在一段時間內的大量刪除操做,會使這種留空的空間變得比存儲列表內容所使用的空間更 大。當MySQL對數據進行掃描時,它掃描的對象實際是列表的容量需求上限,也就是數據被寫入的區域中處於峯值位置的部分。若是進行新的插入操 做,MySQL將嘗試利用這些留空的區域,但仍然沒法將其完全佔用。app

這種額外的破碎的存儲空間在讀取效率方面比正常佔用的空間要低得多。讓咱們看一個實例。post

咱們將建立一個數據庫(有時也稱其爲大綱)及一個測試用的列表:性能

  1. (root@localhost) [test]> create database frag_test;  
  2. Query OK, 1 row affected (0.03 sec)  
  3.  
  4. (root@localhost) [test]> use frag_test;  
  5. Database changed  
  6.  
  7. (root@localhost) [frag_test]> create table frag_test (c1 varchar(64));  
  8. Query OK, 0 rows affected (0.05 sec) 

如今讓咱們在列表中加入以下幾行:測試

  1. (root@localhost) [frag_test]> insert into frag_test values ('this is row 1');  
  2. Query OK, 1 row affected (0.01 sec)  
  3.  
  4. (root@localhost) [frag_test]> insert into frag_test values ('this is row 2');  
  5. Query OK, 1 row affected (0.00 sec)  
  6.  
  7. (root@localhost) [frag_test]> insert into frag_test values ('this is row 3');  
  8. Query OK, 1 row affected (0.00 sec) 

如今咱們進行碎片查看:優化

  1. (root@localhost) [frag_test]> show table status from frag_test\G;  
  2. *************************** 1. row ***************************  
  3.            Name: frag_test  
  4.          Engine: MyISAM  
  5.         Version: 10  
  6.      Row_format: Dynamic 
  7.            Rows: 3  
  8.  Avg_row_length: 20  
  9.     Data_length: 60  
  10. Max_data_length: 281474976710655  
  11.    Index_length: 1024  
  12.       Data_free: 0  
  13.  Auto_increment: NULL 
  14.     Create_time: 2011-02-23 14:55:27  
  15.     Update_time: 2011-02-23 15:06:55  
  16.      Check_time: NULL 
  17.       Collation: latin1_swedish_ci  
  18.        Checksum: NULL 
  19.  Create_options:   
  20.         Comment:   
  21. 1 row in set (0.00 sec) 

如今咱們刪除一行,並再次檢測:

  1. (root@localhost) [frag_test]> delete from frag_test where c1 = 'this is row 2';  
  2. Query OK, 1 row affected (0.00 sec)  
  3.  
  4. (root@localhost) [frag_test]> show table status from frag_test\G;  
  5. *************************** 1. row ***************************  
  6.            Name: frag_test  
  7.          Engine: MyISAM  
  8.         Version: 10  
  9.      Row_format: Dynamic 
  10.            Rows: 2  
  11.  Avg_row_length: 20  
  12.     Data_length: 60  
  13. Max_data_length: 281474976710655  
  14.    Index_length: 1024  
  15.       Data_free: 20  
  16.  Auto_increment: NULL 
  17.     Create_time: 2011-02-23 14:55:27  
  18.     Update_time: 2011-02-23 15:07:49  
  19.      Check_time: NULL 
  20.       Collation: latin1_swedish_ci  
  21.        Checksum: NULL 
  22.  Create_options:   
  23.         Comment:   
  24. 1 row in set (0.00 sec) 

須要注意的是,「data_free」一欄顯示出了咱們刪除第二行後所產生的留空空間。想象一下若是你有兩萬行指令的話,結果是什麼樣的。以此推 算,它們將耗費四十萬字節的存儲空間。如今若是你將兩萬條命令行刪到只剩一行,列表中有用的內容將只佔二十字節,但MySQL在讀取中會仍然將其視同於一 個容量爲四十萬字節的列表進行處理,而且除二十字節之外,其它空間都被白白浪費了。

清理碎片

幸運的是一旦你鎖定了這一問題,MySQL提供了一種簡便的修正方法。這就是所謂的優化列表,具體內容以下:

  1. (root@localhost) [frag_test]> optimize table frag_test;  
  2. +---------------------+----------+----------+----------+  
  3. Table               | Op       | Msg_type | Msg_text |  
  4. +---------------------+----------+----------+----------+  
  5. | frag_test.frag_test | optimize | status   | OK       |   
  6. +---------------------+----------+----------+----------+  
  7. 1 row in set (0.00 sec)  
  8.  
  9. (root@localhost) [frag_test]> show table status from frag_test\G;  
  10. *************************** 1. row ***************************  
  11.            Name: frag_test  
  12.          Engine: MyISAM  
  13.         Version: 10  
  14.      Row_format: Dynamic 
  15.            Rows: 2  
  16.  Avg_row_length: 20  
  17.     Data_length: 40  
  18. Max_data_length: 281474976710655  
  19.    Index_length: 1024  
  20.       Data_free: 0  
  21.  Auto_increment: NULL 
  22.     Create_time: 2011-02-23 14:55:27  
  23.     Update_time: 2011-02-23 15:11:05  
  24.      Check_time: 2011-02-23 15:11:05  
  25.       Collation: latin1_swedish_ci  
  26.        Checksum: NULL 
  27.  Create_options:   
  28.         Comment:   
  29. 1 row in set (0.00 sec) 

性能考量

「優化列表」功能在進行中會對整個列表進行鎖定。對於小型列表,這一功能的效果很是好,由於整個列表的讀取和修改速度都會很快。但對於那些體積巨大的列表來講,這一過程將消耗很長時間,而且其間會中斷或減小可用的應用程序數量。怎麼辦?

再一次,MySQL幸運地提供了一項堪稱偉大的功能,名爲「主-主複製」。 在這種配置之下,你的後臺數據庫實際上成爲兩個單獨的數據庫,一個主動可調用的,一個被動可調整的。這兩個數據庫在各方面來講都是徹底相同的。要實現各類 在線操做——包括「優化列表」操做——只需在你的被動數據庫中便可進行。這將不會對你的應用程序形成絲毫影響。一旦優化操做完成,主、被動數據庫將互相轉 換,以便應用程序直接指向二號數據庫,對還未進行優化的主動數據庫部分自動開始優化工做。

這時,兩套數據庫的角色已經互換,而應用程序也將順利指向二號數據庫,執行與在一號數據庫上相同的列表優化。而如今主動已經轉換爲被動,所以不會中斷主要任務處理。

其它命令

顯示你數據庫中存在碎片的所有列表:

  1. (root@localhost) [(none)]> select table_schema, table_name, data_free, engine from information_schema.tables where table_schema not in ('information_schema', 'mysql') and data_free > 0;  
  2. +--------------+-----------------------------+-----------+--------+  
  3. | table_schema | table_name                  | data_free | engine |  
  4. +--------------+-----------------------------+-----------+--------+  
  5. | aitc         | wp_comments                 |    346536 | MyISAM |   
  6. | aitc         | wp_options                  |     64308 | MyISAM |   
  7. | aitc         | wp_postmeta                 |       124 | MyISAM |   
  8. | cactidb      | poller_item                 |       160 | MyISAM |   
  9. | cactidb      | poller_output               |       384 | MyISAM |   
  10. | drupal       | sessions                    |     30976 | MyISAM |   
  11. | drupal       | users                       |        92 | MyISAM |   
  12. | drupal       | variable                    |        20 | MyISAM |   
  13. | gg           | wp_comments                 |       232 | MyISAM |   
  14. | gg           | wp_options                  |       696 | MyISAM |   
  15. | gg           | wp_postmeta                 |       560 | MyISAM |   
  16. | ihi          | wp_comments                 |       536 | MyISAM |   
  17. | ihi          | wp_options                  |       444 | MyISAM |   
  18. | ihi          | wp_postmeta                 |       288 | MyISAM |   
  19. | ihi          | wp_redirection_items        |      1292 | MyISAM |   
  20. | ihi          | wp_redirection_logs         |    140352 | MyISAM |   
  21. | nds          | wp_comments                 |      4704 | MyISAM |   
  22. | nds          | wp_options                  |    150580 | MyISAM |   
  23. | nds          | wp_postmeta                 |        76 | MyISAM |   
  24. | oos          | wp_comments                 |    317124 | MyISAM |   
  25. | oos          | wp_options                  |     88196 | MyISAM |   
  26. | oos          | wp_postmeta                 |        76 | MyISAM |   
  27. | phplist      | phplist_listuser            |       252 | MyISAM |   
  28. | phplist      | phplist_sendprocess         |        52 | MyISAM |   
  29. | phplist      | phplist_user_user           |     32248 | MyISAM |   
  30. | phplist      | phplist_user_user_attribute |       120 | MyISAM |   
  31. | phplist      | phplist_user_user_history   |       288 | MyISAM |   
  32. | phplist      | phplist_usermessage         |      1428 | MyISAM |   
  33. | pn_nds       | nuke_session_info           |     12916 | MyISAM |   
  34. | psa          | exp_event                   |     10024 | MyISAM |   
  35. | test         | active_sessions             |     30144 | MyISAM |   
  36. +--------------+-----------------------------+-----------+--------+  
  37. 31 rows in set (0.26 sec) 

若是你更改了某個列表的存儲引擎,你也應該對這一列表進行碎片清理。這是由於MySQL的工做原理致使其必須讀取整個列表,而後利用新的存儲引擎將內容寫回磁盤,而在此過程當中碎片所在的位置及影響到的數據都對執行效率形成了嚴重的不良影響。

上述狀況以下所示:

  1. (root@localhost) [frag_test]> alter table frag_test engine = innodb;  
  2. Query OK, 2 rows affected (0.17 sec)  
  3. Records: 2  Duplicates: 0  Warnings: 0  
  4.  
  5. (root@localhost) [frag_test]> show table status from frag_test  
  6.     -> \G;  
  7. *************************** 1. row ***************************  
  8.            Name: frag_test  
  9.          Engine: InnoDB  
  10.         Version: 10  
  11.      Row_format: Compact  
  12.            Rows: 2  
  13.  Avg_row_length: 8192  
  14.     Data_length: 16384  
  15. Max_data_length: 0  
  16.    Index_length: 0  
  17.       Data_free: 0  
  18.  Auto_increment: NULL 
  19.     Create_time: 2011-02-23 15:41:12  
  20.     Update_time: NULL 
  21.      Check_time: NULL 
  22.       Collation: latin1_swedish_ci  
  23.        Checksum: NULL 
  24.  Create_options:   
  25.         Comment: InnoDB free: 7168 kB  
  26. 1 row in set (0.00 sec) 

結論

若是你發現一些列表中包含了大量的數據留空現象,那麼對其進行優化是絕對值得的,由於這一過程會大大提高列表的讀取性能及應用表現。

原文地址:http://www.databasejournal.com/features/mysql/article.php/3927871/article.htm

相關文章
相關標籤/搜索