【问题标题】:MariaDB InnoDB bulk INSERT slow overtimeMariaDB InnoDB 批量 INSERT 慢超时
【发布时间】:2020-05-20 06:48:57
【问题描述】:

目前,我有一个服务器 A,它拥有大约 250 亿条记录(几 TB 大小),结构如下:

CREATE TABLE `table_x` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `a1` char(64) DEFAULT NULL, `b1` int(11) unsigned DEFAULT NULL, `c1` tinyint(1) DEFAULT NULL, `LastUpdate` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`id`), UNIQUE KEY `idxb1a1` (`b1`,`a1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

由于数据变得太大,我正在尝试将这些记录迁移到具有相同架构结构的服务器 B,使用按列 id 的升序批量插入 10K 记录(例如 INSERT INTO yourtable VALUES (1,2), (5,5), ...;)。

最初,插入速度非常快 - 但是,它逐渐变慢,现在大约需要 10 秒才能批量插入 10K 记录(即 1K/秒)。 我猜是因为它需要在每次插入后更新索引。

在开始迁移之前,我在服务器 B 上做了如下配置:

  • innodb_flush_log_at_trx_commit=2
  • SET unique_checks=0;
  • autocommit=0 并每 50K 提交一次

服务器 B 硬件配置:

  1. 300GB+ 内存(240GB 用于innodb_buffer_pool_size
  2. 用于数据存储的 SSD

服务器 B my.cnf:

innodb_buffer_pool_size=240G
innodb_buffer_pool_instances=64
innodb_page_cleaners=32

innodb_purge_threads=1

innodb_read_io_threads=64
innodb_write_io_threads=64
innodb_use_native_aio=0
innodb_flush_log_at_trx_commit=2
innodb_doublewrite=0
innodb_autoinc_lock_mode=2
innodb_file_per_table=1
max_connections=10000
skip_name_resolve=1

tmp_table_size=134217728
max_heap_table_size=134217728

back_log=1000
wait_timeout=900

innodb_log_buffer_size=32M
innodb_log_file_size=768M

还有什么我可以做或配置来加快插入速度的吗?

更新 #1:

我尝试将记录迁移到服务器 B 的原因是因为我想将数据拆分/分片到几台服务器(使用 MariaDB SPIDER 引擎分片解决方案)。因此,涉及发送数据快照或直接复制数据的解决方案似乎不可行。

【问题讨论】:

  • 您猜测索引是原因;也许尝试删除 idxb1a1 索引,并在加载所有数据后读取它? (这将复制整个表,因此需要足够的额外磁盘空间)。顺便说一句,在您进行迁移时,似乎是升级到 utf8mb4 的绝佳机会。
  • @ysth 删除索引和重建的时间会比实际迁移时间长吗?
  • 您是否考虑过基于文件的副本? (例如,关闭服务器并复制数据目录/使用备份/...)
  • @Solarflare 无法关闭,因为服务器正在生产,我想减小表中的记录大小(这意味着我不能简单地复制和粘贴)。

标签: mysql innodb bulk insertion


【解决方案1】:

它变慢的原因很可能是因为您的事务日志已满且清除速度跟不上。增加 innodb_log_file_size (需要关闭 innodb_fast_shutdown=0 并删除日志)和 innodb_log_files_in_group 将推迟减速。增加 innodb_io_capacity 和 innidb_io_capacity_max 以匹配您的存储可以实现的目标应该会有所帮助。

为什么不使用 xtrabackup 进行时间点复制和复制以完成同步?这将比 INSERT-ing mysqldump 样式快几个数量级。

【讨论】:

  • @Gordon Bobic 我不使用快照功能(如 xtrabackup)的原因是实际上服务器 B 将保存数据的子集,而服务器 C 将保存剩余的数据。感谢您对配置的建议 - 我会尝试一下。
  • 您可能想查看:1) 分区 2) mysqldump 的 --where 选项。 3) MariaDB的蜘蛛引擎
  • @Gordon Bobic 1) 由于我的架构有 2 个唯一索引,因此无法进行分区。 2) 谢谢,我会探索一下 mysqldump --where 选项过程是否总体上比迁移快 3) 是的,实际上这就是我将这些记录分解为更小的服务器的确切原因。这样我就可以使用 MariaDB Spider 引擎了
  • @GitPirateFlare - 所以你要设置“分片”?是什么决定了机器之间的分裂?
  • @Rick James 由于 db 架构,我不得不为 mariadb 蜘蛛解决方案工作做一个变通方法。蜘蛛将删除唯一键约束idxb1a1,以便我可以使用id(范围分区)设置分区(指向数据服务器)-但是,在数据服务器上,它们将保留唯一键约束
【解决方案2】:

除了来自@Gordon-bobic 的答案之外,删除索引并在最后重新应用会大大加快速度。

【讨论】:

  • 我担心的是,由于数据大小(以 TB 为单位),重建索引将花费难以想象的时间
  • 是的,它会的,但是逐渐地这样做会花费更多的时间——毕竟你必须写入 TB 的数据。没有办法解决这个问题。我听说的 Spotifiy 数据库迁移花了一年时间......他们仍然丢失了 0.2% 的数据......是 codetalks 2019 上的一个演讲
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-02
  • 1970-01-01
  • 2018-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多