2017-04-20 62 views
1

如何更新25 GB的大型表,超過3.5億條MyISAM記錄? 我需要在time字段中爲所有記錄設置一個隨機日期。在沒有負荷的服務器,命令被執行:如何更新25 GB的大型表,超過3.5億條MyISAM記錄?

UPDATE table SET time = FROM_UNIXTIME(1451595600 + FLOOR((RAND() * 31536000))) 

mysqld的加載處理器和佔用了大量的內存,在上午的負載服務器是最小的,但所有執行查詢,超過55小時過去了。

enter image description here

我不明白這是怎麼回事!

CREATE TABLE `table` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `job_id` int(10) unsigned NOT NULL, 
    `lock` mediumint(6) unsigned DEFAULT '0', 
    `time` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `job_id` (`job_id`), 
    KEY `lock` (`lock`), 
    KEY `time` (`time`) 
) ENGINE=MyISAM; 

地址:

[email protected]:~ # iostat -p md1 60 5 

enter image description here

解決:

我打斷更新過程。

除主刪除索引:

MariaDB [base]> ALTER TABLE `table` DROP INDEX `job_id`, DROP INDEX `lock`, DROP INDEX `time`; 
Query OK, 339468609 rows affected (1 hour 3 min 28.89 sec) 
Records: 339468609 Duplicates: 0 Warnings: 0 

更新`time`字段:

MariaDB [base]> UPDATE `table` SET `time` = FROM_UNIXTIME(1451595600 + FLOOR((RAND() * 31539599))); 
Query OK, 339468609 rows affected (16 min 8.09 sec) 
Rows matched: 339468609 Changed: 339468609 Warnings: 0 

添加索引:

MariaDB [base]> ALTER TABLE `table` ADD INDEX (`job_id`), ADD INDEX (`lock`), ADD INDEX (`time`); 
Query OK, 339468609 rows affected (2 hours 18 min 58.32 sec) 
Records: 339468609 Duplicates: 0 Warnings: 0 

總更新時間:3小時38分鐘35.3秒

+0

對不起,但你的問題很難理解。請更確切地說:_查詢查詢是否正確結束?列是否已更新? – arkascha

+0

這張表上的索引可能很有意思。請將關於創建表和索引的信息添加到問題中。 – arkascha

+0

表格仍在更新中,但我擔心已經很長時間了。此時大部分時間服務器未加載 – Dmitry

回答

2

首先, 刪除該表的所有索引。另外,如果有的話,丟棄外鍵約束。然後火災更新查詢。更新完成後,再次創建所有索引和約束

所有索引和約束的創建都需要時間,但與直接更新表相比,它會少得多。

+0

誰給這個答案投了票,爲什麼?這可能不一定是這個問題的答案,但這些提示無疑是有道理的! – arkascha

+0

(1)MyISAM不支持FK; (2)刪除所有索引是矯枉過正的。 –

+0

我中斷了更新過程。刪除除主要更新\'時間\'字段以外的索引,添加索引。總更新時間:3小時38分鐘35.3秒 – Dmitry

0

這是發生了什麼...

每條記錄​​最初是13個字節。更新一行後,它將是17個字節(MySQL的舊版本)或18個字節(新版本)。

這意味着更新的行不能簡單地替換舊行,但必須放在其他位置,然後釋放舊空間。第一次這樣的更新將會結束。或者,也許它會使用舊空間的13-6個字節,然後將鏈接放置到放置新行剩餘部分的位置。

第二行然後做一些類似的雜亂。

因此,該操作是在表格中綁定,並使數據非常分散。

此外,time索引正在重建(使用key_buffer)。由於它是「隨機的」,所以對BTree指數的更新是隨機的。如果key_buffer不夠大,那麼會有很多I/O。可以通過事先索引DROPping來加速這個特定方面,然後重新添加它。唉,DROPADD都會很慢,但不會像增量構建索引那麼慢。

你真的應該轉向InnoDB,它可以完全不同地改變數據更新和索引更新,並且更有效。一個警告:表+索引將佔用MyISAM磁盤空間的2-3倍。

你真的需要所有4個索引嗎?

對於MyISAM,值爲key_buffer_size很重要。對於InnoDB,innodb_buffer_pool_size