【发布时间】:2018-01-24 01:45:32
【问题描述】:
我正在尝试对大约 200,000 个现有 MySQL 行执行批量更新。更具体地说,我需要更新这些行中的 8 个空 LONG BLOB 字段,每个字段都有一个 ~ 0.5 Mb 的文件(使用 LONG BLOB 是因为存在一些特殊情况,其中存储了非常大的文件;但是,这些不在此批量中考虑更新)。需要插入的文件存储在本地磁盘上。
我正在使用我编写的 MATLAB 脚本循环遍历存储这些文件的每个文件夹,读取文件并将它们转换为十六进制表示,然后执行 UPDATE 查询以使用八个文件更新八列每一行。
最初,事情进展得相当快。然而,我注意到在完成了几千次查询之后,事情真的开始变慢了。我对优化 MySQL 和 InnoDB 系统变量做了一些研究,将innodb_buffer_pool_size 增加到 25G,innodb_buffer_pool_instances 增加到 25。
经过这次修改后,事情再次加快了速度,但在又进行了几千次查询后速度变慢了。我做了更多的研究,并试图弄乱一些其他变量,例如 innodb_log_buffer_size 和 innodb_log_file_size 将两者都增加到 100M 只是为了看看会发生什么。我还将innodb_write_io_threads 和innodb_read_io_threads 设置为16,因为我在具有32 GB RAM 的相当高端的服务器上运行这一切。不幸的是,这些修改并没有太大帮助,现在我遇到了每个需要几分钟才能完成的查询。
是否有人对我如何优化此过程并使其尽可能快地运行有任何建议或想法?
谢谢,
乔
【问题讨论】:
-
系统的吞吐量受到 i/o 操作(硬盘的速度)的限制。它变慢通常是完全读/写缓存(包括可能缓存了实际源文件的操作系统缓存)的影响 - 但您最终必须写入磁盘。所以请告诉我们硬盘速度,(较慢的)更新速度以及源是否与数据库在同一磁盘上,以估计它是否太慢。您可以尝试的事情:确保您使用索引标识您的行(例如
update...where id=4,id 主键)。定期提交,但不是在每一行之后;尝试例如每 100-500 行。 -
您好 Solarflare,我们使用由几个 4 TB SAS 6 Gb/s 7200 RPM 服务器级 HDD 组成的 RAID 5 阵列,总共构成大约 36 TB 的存储空间。源文件确实与数据库位于同一存储空间。将源文件移动到另一个存储空间会提高性能吗?另外,我正在使用主键索引来识别行。
-
系统规格没有多大帮助。将最大 i/o(基准)与实际 i/o 进行比较。检查例如Windows 的资源监视器或 linux 的 iotop/dstat。将其与您的(较慢的)更新吞吐量进行比较(例如,如果您每秒插入 5 行,每行正好 8 次 0.5mb,读写速度为 20mb/s),以检查 i/o 是否是瓶颈。将源文件放在不同的驱动器上可以提高写入速度(但如果不是,则必须首先将它们复制到执行时间中)。还要尝试提交频率。另外:也许只是将数据保存在文件系统/smb 共享中而不是数据库中。
-
感谢@Solarflare 的所有帮助。我想我发现了问题。在启动脚本之前,我删除了除主键之外的所有索引,因为我认为它们会对性能产生负面影响。之前我说我是通过主键识别 UPDATE 查询中的行时我错了。我实际上是通过删除索引的辅助列来识别行。运行
SHOW ENGINE INNODB STATUS后,我看到了大约 300+ 秒。为 UPDATE 查询花费了获取行。我为这个专栏重新添加了索引,从那以后一切都加快了。
标签: mysql sql matlab performance sql-update