繁体   English   中英

MariaDB InnoDB 批量 INSERT 超时慢

[英]MariaDB InnoDB bulk INSERT slow overtime

目前,我有一个服务器 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;

由于数据增长太大,我正在尝试使用批量插入 10K 条记录(例如INSERT INTO yourtable VALUES (1,2), (5,5), ...; ) 按列id的升序排列。

最初,插入速度非常快——然而,它逐渐变慢,现在大约需要 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 引擎分片解决方案)。 因此,涉及发送数据快照或直接复制数据的解决方案似乎不可行。

它变慢的原因可能是因为您的事务日志已满并且清除没有跟上。 增加 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 的答案之外,删除索引并在最后重新申请会大大加快速度。

同意@gordan-bobić 关于xtrabackup的使用。 如果你正在申请数据迁移,如果你想要速度,使用物理副本/备份是你最好的方法。 使用诸如使用mysqldump之类的逻辑副本或基于查询的副本可能会花费很多时间,因为它必须根据在运行时加载并动态完成的配置集应用检查。 但是,如果批量插入是您的选择,那么请考虑调整innodb_autoinc_lock_mode = 2 (如果适用)。

另一件事是,如果您使用INSERT语句,您是否一次加载一个值? 考虑使用多值列表,因为这被证明更快。 另一方面,也可以考虑使用LOAD DATA而不是INSERT语句。

还有你的innodb_change_buffering=insert (因为你在 MariaDB 中使用unique_checks=0 )并考虑增加innodb_change_buffer_max_size例如从3050 当您要插入的目标表上没有太多活动时,最好执行此操作,以便您可以监视目标数据库服务器上的此类活动。 还要考虑到在该目标服务器上运行的其他应用程序或守护进程也没有太多干扰。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM