加速alter table

MySql的ALTER TABLE 操作的性能對大表來說是個大問題。MySQL執行大部分修改表結構操作的方法是新建一個需要的結構的空表從舊錶中查出所有數據插入新表,然後刪除舊錶。這樣操作肯需要花費很長時間,如果內存不足而表又很大,而且還有很多索引的情況下尤其如此。許多人都有這樣的經驗。ALTER TABLE操作需要花費數個小時甚至數天才能完成。

MySQL5.1以及更新版本包含一些類型的“在線”操作的支持,這些功能不需要在整個操作過程中鎖表。最近版本的InnoDB也支持通過排序來建索引,這使得建索引更快並且有一個緊湊的佈局。

一般而言,大部分ALTER TABLE操作將導致MySQL服務中斷。我們會展示一些在DDL操作時使用的技巧,但這是針對一些特殊場景而言的。對常見的場景,能使用的技巧只有兩種:一種是先在一臺不提供服務的機器上執行ALTER TABLE操作,然後和提供服務的主庫進行切換;另外一種技巧是“影子拷貝”。影子拷貝的技巧是用要求的表結構創建一張和源表無關的新表,然後通過重命名和刪表操作交換兩張表。

不是所有的ALTER TABLE操作都會引起表重建。例如,有兩種方法可以改變或者刪除一個列的默認值(一種方法很快,另外一種則很慢)。假如要修改電影的默認租賃期限,從三天到五天。下面是很慢的方式:

mysql> ALTER TABLE sakila.film

         ->MODIFY COLUMN rental_duration TINYINT(3)  NOT NULL DEFAULT 5;

SHOW STATUS 顯示這個語句做了1000次讀和1000次插入操作。換句話說,它拷貝了整張表到一張新表,甚至列的類型,大小和可否爲NULL屬性都沒改變。

理論上,MySQL可以跳過創建新表的步驟。列的默認值實際上存在表的.frm文件中,所以可以直接修改這個文件而不需要改動表本身。然而MySQL還沒有采用這種優化的方法,所有的MODIFY COLUMN操作都將導致表重建。

另外一種方法是通過ALTER COLUMN操作來改變列的默認值:

mysql>ALTER TABLE sakila.film

         ->ALTER COLUMN rental_duration SET DEFAULT 5;

這個語句會直接修改.frm文件而不涉及表數據。所以,這個操作是非常快的。

只修改.frm文件

  修改表的.frm文件是很快的,但MySQL有時候會在沒有必要的時候也重建表。如果願意冒一些風險,可以讓MySQL做一些其他類型的修改而不用重建表。

下面這些操作是有可能不需要重建表的:

  • 移除(不是增加)一列的AUTO_INCREMENT屬性。
  • 增加、移除,或更改ENUM和SET常量。如果移除一個常量和含有該常量的行,查詢將會返回一個空字串值。

基本技巧是爲想要的表結構創建一個新的.frm文件,然後用它替換掉已經存在的那張表的.frm文件,像下面這樣: 
  1. 創建一張有相同結構的空表,並進行所需要的修改(例如增加ENUM常量)。 
  2. 執行FLUSH WITH READ LOCK。這將會關閉所有正在使用的表,並且禁止任何表被打開。 
  3. 交換.frm文件(重全名)。 

  4. 執行UNLOCK TABLES來釋放第2步的讀鎖。

快速的創建MyISAM索引

  高效的讀取MyISAM表一般的技巧是,關閉鍵,讀取數據,重新啓用鍵。

  mysql> ALTER TABLE test.load_data DISABLE KEYS; 
  -- load the data 
  mysql> ALTER TABLE test.load_data ENABLE KEYS;

  這樣可以工作的原因是MyISAM延遲了創建鍵值直到數據讀取之後,重要的是,它可以有序的創建索引。結果就非常快並且會得到無碎片和緊湊的索引樹。

  不過,對於唯一索引這種方法就不行了。因爲DISABLE KEYS僅僅應用於非唯一索引。MyISAM在內存中創建唯一索引並且讀取每一行來校驗唯一性。一旦索引大小超出了內存大小,讀取會極度緩慢。

  前一部分所說的ALTER TABLE的技巧,可以加速這個過程,前提是你需要多做一點工作和承擔一部分風險。這對於備份來說很有用。比如,當你發現所有的數據是無效的並且不需要做唯一性檢查。

  你需要做的步驟如下:

  1、創建一個有需要的結構的表。但是不要有任何的索引。

  2、把數據加載到表中來創建.MYD文件。

  3、創建另一個有需要的結構的空表,這次要包含索引。這會創建.frm和.MYI文件。

  4、用個讀鎖來刷新表。

  5、對第二個表的.frm和.MYI進行重命名。因此MySQL會把它們當作第一個表使用。

  6、釋放讀鎖。

  7、使用REPAIR TABLE來創建表的索引。會以排序的方式創建索引,包括了唯一索引。

  這個方法對於大表來說,速度格外的快。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章