2017-04-20 68 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