加速MySQL的alter table操作

2021-09-29 00:14:15 字數 2948 閱讀 8651

mysql的alter table效能在表很大的時候會出現問題。mysql執行大部分更改操作都是新建乙個需要的結構的空表,然後把所有老的資料插入到新錶,最後刪除舊表。這會耗費很多時間,尤其是在記憶體緊張,而表很大並有很多索引的時候。

不是所有的alter table操作都會導致重建表。例如,可以通過兩種方式建立或去掉列的預設值(一種快、一種慢)。下面是較慢的方式:

alter table film modify column rental_duration tinyint(3) not null default 5;

使用show status分析該命令發現,它執行了1001次控制代碼讀取和1000次寫入。換句話說,即使列型別、大小和可空性沒有變化,它也把表拷貝到了新錶中。

flush status;

alter table film modify column rental_duration tinyint(3) not null default 5;

show session status like 'handle%';

variable_name    value

handler_commit     2

......    

handler_read_rnd_next    1001

......    

handler_write    1000

理論上,mysql能跳過構建乙個新錶的方式。列的預設值實際儲存在表的.frm檔案中,因此可以不接觸表而更改它。mysql沒有使用這種優化,而是任何modify column都會導致表重建。但是可以使用alter column改變列的預設值:

alter table film alter column rental_duration set default 5;

這個命令更改了.frm檔案並且沒有改動表,它非常快。(alter table可以使用alter column、modify column、change column來修改列,每個命令做的事情都不一樣)。

flush status;

alter table film modify column rental_duration tinyint(3) not null default 5;

show session status like 'handle%';

variable_name

value

handler_commit     2

......    

handler_read_rnd_next    0

......    

handler_write    0

1. 只修改.frm檔案

下面這種技巧不被mysql支援,也沒有文件記載,而且不保證一定能工作。使用它們需要自己承擔風險,建議在使用之前備份資料。

不重建表可以執行下面的操作:

移除(不是新增)列的auto_increment屬性。

新增、移除或更改enum或set常量。如果移除了乙個常量,查詢含有該常量的行將返回空字串。

基本的技巧是為想要的表結構建立乙個.frm檔案來替代現有的.frm檔案,步驟如下:

建立乙個布局完全一樣的空表,但是想改動的地方除外(例如新增enum的常量)。

執行flush tables with read lock。這會關閉所有正在使用的表,並且防止任何表被開啟。

交換.frm檔案。

執行unlock tables釋放讀鎖。

例子:向film表的rating列新增乙個常量,當前列定義如下:

show columns from film like 'rating';

field    type    null    key    default

rating    enum('g','pg','pg-13','r','nc-17')    yes    

g現在增加乙個pg-14:

create table film_new like film;

alter table film_new modify column rating enum('g','pg','pg-13','r','nc-17','pg-14') default 'g';

flush tables with read lock;

現在從系統的命令列交換.frm檔案:

mv film.frm film_tmp.frm

mv film_new.frm film.frm

mv film_tmp.frm film_new.frm

回到mysql命令列,現在可以給表解鎖並檢視改動是否生效;

unlock tables;

show columns from film like 'rating';

field    type    null    key    default

rating    enum('g','pg','pg-13','r','nc-17','pg-14')    yes    

g最後刪除用來輔助該操作的表:

drop table film_new;

注意新值被新增到常量列表的末尾,如果放到中間,如在pg-13之後,就更改了已有資料的含義:已有r值就會變成pg-14,nc-17就會變成r,等等。

2. 快速建立myisam表的索引

高效載入myisam表的訣竅是禁用鍵、載入資料、啟用鍵:

alter table load_data disable keys;

-- load the data

alter table load_data enable keys;

這不會有問題,因為它使myisam直到所有資料被載入後才建立鍵,在這個時候,它可以按照排序構建索引。它很快並且會得到無碎片、緊湊的索引樹(myisam在使用load data infile和空表的時候也會按照排序建立索引)。

不幸的是,disable keys只適用於非唯一索引。myisam在記憶體中構建唯一索引並且在載入每一行的時候檢驗其唯一性,一旦索引的大小超過可用記憶體,載入就變得極為緩慢。

mysql 匯入資料加速 MySQL加速匯入資料

修改配置 關閉binlog 避免寫入日誌set sql log bin off 匯入完成還原配置set sql log bin on 調整innodb flush log at trx commit 加快資料刷盤速度。set global innodb flush log at trx commit...

加速 MySQL 匯入匯出的方法

mysql匯出的sql語句在匯入時有可能會非常非常慢,在處理百萬級資料的時候,可能匯入要花幾小時。在匯出時合理使用幾個引數,可以大大加快導 入的速度。e 使用包括幾個values列表的多行insert語法 max allowed packet 客戶端 伺服器之間通訊的快取區的最大大小 net buf...

加速MySQL匯入匯出的方法

加速mysql匯入匯出的方法 mysql匯出的sql語句在匯入時有可能會非常慢,在處理百萬級資料的時候,可能匯入要花幾小時。在匯出時合理使用幾個引數,可以大大加快匯入的速度。e 使用多行insert語法,給出更緊縮並且更快的插入語句 max allowed packet 客戶端 伺服器之間通訊的快取...