2

我有一张 1760 万行的表

'CREATE TABLE `tmp_hist` (
`ti` int(11) DEFAULT NULL,
`cip6` varchar(15) DEFAULT NULL,
`date` varchar(20) DEFAULT NULL,
`fact` int(11) DEFAULT NULL,
`se` char(1) DEFAULT NULL,
`oper` int(11) DEFAULT NULL,
`qte` int(11) DEFAULT NULL,
`prix` double DEFAULT NULL,
`cip` int(11) DEFAULT NULL,
`fl` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1'

运行一个非常简单的更新大约需要 10 分钟

update tmp_hist set cip=100

有的时候:

  • 39sec -- 修复表 tmp_hist(这个特别有趣,因为在 myisam 中,修复表会将其复制到不同的文件并替换原始文件,这表明磁盘速度)
  • 531sec -- 更新 tmp_hist 设置 cip=100
  • 400sec -- CREATE TABLE tmp_inno SELECT * FROM tmp_hist (这里我尝试将表转换为 InnoDB)
  • 317sec -- 更新 tmp_inno 设置 cip=999(这个在 InnoDb 中)

根据所有假设,我希望更新时间与修复时间非常相似,即 40 秒。但是需要10分钟!可以做些什么来加快速度?有问题的代码将一些数据从格式 A 转换为格式 B。它保证在单个线程中运行,没有其他人访问相同的数据,如果出现任何问题,也不需要恢复,它可以重新开始。

PS:为了测试,UPDATE 语句被简化了(所有时间都是为了这个简化的更新)。真实代码为每一行设置不同的值,但我发现真实更新的执行时间与简化更新几乎相同,所以我将问题缩小到简化。

目前的进展

使用答案中的知识,我应用了 ROW_FORMAT=FIXED (这似乎相当于将所有列类型更改为固定)并将更新时间减少到 145 秒,几乎快了 4 倍。

尽管如此,它还是比修复时间慢了大约 2.5 倍,我认为这是可以达到的时间。

4

1 回答 1

4

由于您varchar的表中有 s,因此更新必须读取该行,查找正确的偏移量,然后更新 cip 字段。此外,由于行是可变大小的,引擎不能轻易确定单个记录的偏移量。因此,您可以尝试将您的varchar字段更改为固定char并进行测试,如果这会有所不同。

dba SE https://dba.stackexchange.com/a/2643的一个有趣的答案也涵盖了这个主题

于 2012-12-06T11:07:41.290 回答