mysql optimize table

來源:互聯網
上載者:User

標籤:bsp   建立   負載   ORC   儲存空間   測試   線上   片段   索引   

文法結構:

OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL]    TABLE tbl_name [, tbl_name] ...

optimize table 會重組表資料和索引的實體儲存體,減少對儲存空間使用和提升訪問表時io效率。optimize table後,表的變化和儲存引擎也有關。

以下情境使用 optimize table,和表的類型有關:
1.innodb儲存引擎+獨立資料表空間,optimize table會重組表和索引資料,磁碟空間被回收。
2.插入、更新、刪除的列是innodb表中fulltext索引的列,要先設定innodb_optimize_fulltext_only=1。
為了將對索引的維護設定在一個合理的時間內,可以設定innodb_ft_num_word_optimize指定一次處理多少個words,執行多次optimize table操作直到索引更新結束。
3.刪除myisam、archive儲存引擎表中大量資料,或者對myisam、archive表變長的行做了大量修改。刪除的行被為維護在一個鏈表中,之後的insert可以重用這些位置。
可以使用optimize TABLE來回收未使用的空間並整理資料檔案。在對錶進行了大量更改之後,該語句還可以提高使用該表的語句的效能,有時效果顯著。

optimize table需要對錶具有select、insert許可權。


optimize table支援innodb、myisam、archive儲存引擎的表。


預設是不支援其他儲存引擎的表,會返回不支援的提示資訊。要想支援其他儲存引擎,可以使用mysqld --skip-new選項開啟對其他儲存引擎的支援。使用--skip-new選項後,optimize table僅僅被映射成alter table操作。


不支援對view進行optimize。


optimize table支援分區表。

預設,optimize table被記入二進位日誌,並複製到slave節點。可以使用no_write_binlog或local取消對二進位日誌的寫入。

 

對innodb表執行optimize table

對於innodb表,optimize table被映射成alter table ... force,重建表和更新索引統計資訊並釋放空間。
對innodb執行optimize table操作,輸出類似下面的結果:

> OPTIMIZE TABLE foo;+----------+----------+----------+-------------------------------------------------------------------+| Table    | Op       | Msg_type | Msg_text                                                          |+----------+----------+----------+-------------------------------------------------------------------+| test.foo | optimize | note     | Table does not support optimize, doing recreate + analyze instead || test.foo | optimize | status   | OK                                                                |+----------+----------+----------+-------------------------------------------------------------------+

optimize table對innodb常規表、分區表執行線上ddl,減少了並發dml操作的宕機時間。

optimize table 觸發表重建,內部執行alter table ... force操作。
在prepare階段和commit階段會對錶加上獨佔鎖定。在prepare階段會更新中繼資料並建立一個內部中間表,在commit階段提交對中繼資料的修改。

 

optimize table在以下情境使用資料拷貝的方式進行重建表:
1.開啟了old_alter_table系統變數
2.使用了mysqld --skip-new選項啟動資料庫

不是所有的情境都可以使用線上ddl。如果innodb表包含fulltext索引,是不支援optimize table的線上ddl的。只能使用資料拷貝的方式。

alter table使用的是資料copy;alter table ... force使用的是線上ddl。

InnoDB使用頁面分配方法儲存資料,不像傳統儲存引擎(比如MyISAM)那樣存在片段問題。執行optimize table之前要考慮事務的負載大小:
·有些層級的片段是系統預期的。innodb只會插入資料到頁面的93%,剩下的空間是給update預留的,以免出現頁的分裂
·刪除操作可能會留下很多空隙,執行optimize table是有意義的
·更新通常是在相同的頁中重寫資料,空間是否充足取決於行格式和列的資料類型
·由於innodb的mvcc機制,高並發環境可能會導致索引產生空隙

 

對myisam表執行optimize table
對於myisam表,optimize table操作執行以下工作:
1.如果表含有刪除的列、分列的列,optimize table會修複表
2.如果索引頁沒有排序,optimize table會將索引頁進行排序
3.如果表的統計資訊不是最新的,optimize table會更新索引資訊

 

補充:

對innodb表執行optimize table操作的時候,會報"Table does not support optimize, doing recreate + analyze instead"提示。有人直接說optimize table不支援innodb表。其實並不能這麼理解。

下面是測試結果:

Server version: 5.7.19 MySQL Community Server (GPL)CREATE TABLE m_test(id int unsigned, body text) engine=myisam charset=utf8;CREATE TABLE i_test(id int unsigned, body text) engine=innodb charset=utf8;INSERT INTO m_test VALUES(1, ‘AAAAA‘);INSERT INTO m_test VALUES(2, ‘BBBBB‘);INSERT INTO m_test VALUES(3, ‘CCCCC‘);INSERT INTO m_test VALUES(4, ‘DDDDD‘);INSERT INTO m_test VALUES(5, ‘EEEEE‘);INSERT INTO i_test VALUES(1, ‘AAAAA‘);INSERT INTO i_test VALUES(2, ‘BBBBB‘);INSERT INTO i_test VALUES(3, ‘CCCCC‘);INSERT INTO i_test VALUES(4, ‘DDDDD‘);INSERT INTO i_test VALUES(5, ‘EEEEE‘);#多次插入相同的資料:INSERT INTO m_test SELECT id, body FROM m_test;INSERT INTO i_test SELECT id, body FROM i_test;...

查看錶和檔案的大小:

ysql> select count(*) from m_test;+----------+| count(*) |+----------+| 83886080 |+----------+1 row in set (0.00 sec)mysql> select count(*) from i_test;+----------+| count(*) |+----------+| 83886080 |+----------+1 row in set (36.04 sec) #明顯慢很多mysql> # ll |grep test-rw-r----- 1 mysql mysql       8586 Sep  2 10:03 i_test.frm-rw-r----- 1 mysql mysql 3267362816 Sep  2 10:30 i_test.ibd-rw-r----- 1 mysql mysql       8586 Sep  2 10:03 m_test.frm-rw-r----- 1 mysql mysql 1677721600 Sep  2 10:26 m_test.MYD-rw-r----- 1 mysql mysql       1024 Sep  2 10:26 m_test.MYI

刪除一定資料後查看錶和檔案的大小:

mysql> DELETE FROM i_test WHERE id < 3;mysql> DELETE FROM m_test WHERE id < 3;# ll |grep test-rw-r----- 1 mysql mysql       8586 Sep  2 10:03 i_test.frm-rw-r----- 1 mysql mysql 3267362816 Sep  2 10:39 i_test.ibd-rw-r----- 1 mysql mysql       8586 Sep  2 10:03 m_test.frm-rw-r----- 1 mysql mysql 1677721600 Sep  2 10:37 m_test.MYD-rw-r----- 1 mysql mysql       1024 Sep  2 10:37 m_test.MYImysql> select count(*) from m_test;+----------+| count(*) |+----------+| 50331648 |+----------+1 row in set (0.00 sec)mysql> select count(*) from i_test;+----------+| count(*) |+----------+| 50331648 |+----------+1 row in set (52.91 sec)

分別執行optimize table操作:

mysql> optimize table m_test;+-------------+----------+----------+----------+| Table       | Op       | Msg_type | Msg_text |+-------------+----------+----------+----------+| test.m_test | optimize | status   | OK       |+-------------+----------+----------+----------+1 row in set (8.49 sec)mysql> optimize table i_test;+-------------+----------+----------+-------------------------------------------------------------------+| Table       | Op       | Msg_type | Msg_text                                                          |+-------------+----------+----------+-------------------------------------------------------------------+| test.i_test | optimize | note     | Table does not support optimize, doing recreate + analyze instead || test.i_test | optimize | status   | OK                                                                |+-------------+----------+----------+-------------------------------------------------------------------+2 rows in set (47.73 sec)mysql> # ll |grep test-rw-r----- 1 mysql mysql       8586 Sep  2 10:42 i_test.frm-rw-r----- 1 mysql mysql 2243952640 Sep  2 10:43 i_test.ibd-rw-r----- 1 mysql mysql       8586 Sep  2 10:03 m_test.frm-rw-r----- 1 mysql mysql 1006632960 Sep  2 10:41 m_test.MYD-rw-r----- 1 mysql mysql       1024 Sep  2 10:41 m_test.MYI

從上面的結果可以看到,無論是innodb、還是myisam表都被收縮了。

 

使用mysqld --skip-new重啟mysqlserver後,再次對innodb表執行optimize table操作:

mysql> optimize table i_test;Query OK, 50331648 rows affected (3 min 10.82 sec)Records: 50331648  Duplicates: 0  Warnings: 0mysql> # ll |grep test-rw-r----- 1 mysql mysql       8586 Sep  2 10:47 i_test.frm-rw-r----- 1 mysql mysql 1962934272 Sep  2 10:50 i_test.ibd-rw-r----- 1 mysql mysql       8586 Sep  2 10:03 m_test.frm-rw-r----- 1 mysql mysql 1006632960 Sep  2 10:41 m_test.MYD-rw-r----- 1 mysql mysql       1024 Sep  2 10:41 m_test.MYI

可以看到,innodb表再次發生了收縮。

 

結論:
"Table does not support optimize, doing recreate + analyze instead"並不是說innodb不支援optimize table。
因為對於innodb表,optimize table被映射成alter table ... force,重建表和更新索引統計資訊並釋放空間。

 

mysql optimize table

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.