MySQL 在大型数据集上使用 IN 更新时速度缓慢

标签 mysql sql

我需要通过各种来源更新主数据集,这些来源为某些现有记录提供了一些更改,例如新的手机号码。

每个查询的执行时间都在10小时以上。

环境:MySQL 8、8 核 CPU、32 GB 内存。

我有以下主表,它保存atm 3M记录:

CREATE TABLE `contact_data` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `email_status` tinyint(3) unsigned DEFAULT '0',
  `mobile_phone` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `firstname` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `lastname` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `nickname` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`email`),
  UNIQUE KEY `id` (`id`),
  KEY `country` (`country`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

到目前为止我已经尝试通过各种方式进行更新。源表大多只有 10K - 100K 条记录。我尝试使用 MyISAM 和“id”作为主键进行相同的操作。

加入:

UPDATE contact_data cd
LEFT JOIN (SELECT email, firstname FROM source2 WHERE firstname <> '' GROUP BY email ORDER BY id DESC) AS t2
ON cd.email = t2.email
SET cd.firstname = t2.firstname

直接:

UPDATE contact_data SET mobile_phone = (SELECT phone FROM source1 WHERE email = contact_data.email ORDER BY id DESC LIMIT 1) 
WHERE mobile_phone IS NULL 

直接但有记录限制:

UPDATE contact_data SET mobile_phone = (SELECT phone FROM source1 WHERE email = contact_data.email ORDER BY id DESC LIMIT 1) 
WHERE mobile_phone IS NULL 
AND email IN (SELECT DISTINCT email FROM source1)

配置:

innodb_buffer_pool_size = 16G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_log_buffer_size = 10M

key_buffer_size = 512M

对配置文件进行更多调整大多会带来微小的改进。

有什么我可以尝试的吗?

最佳答案

首先,您需要通过删除电子邮件重复项并在电子邮件字段上添加主/唯一索引来准备源表。

其次,因为您的源表比主表更小,您可以使用下一个查询:

UPDATE source s
JOIN contact_data cd ON s.email = cd.email
SET cd.mobile_phone = s.mobile_phone;

第三,您可以通过使用 mysqltuner 调整 MySQL 配置来提高更新性能或任何其他乐器

关于MySQL 在大型数据集上使用 IN 更新时速度缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59765740/

相关文章:

java - JPA 的 SQL 结构-行还是列?

mysql - 匹配mySQL中两条记录中的值

mysql - SQL UNION 语句位于彼此之下

sql - 合并和案例陈述 - 解释?

mysql - 最佳 SQL 解决方案?

php - 我无法插入文本区域值

java - 从 mysql 中以 block 的形式读取一个大的结果集

mysql - 需要一个想法来设计用于诊所预约安排的数据库 : "A doctor is working in multiple clinics in different timings"

MySQL GROUP_CONCAT 作为多个字段和自定义顺序

mysql - 创建mysql View 时如何在字段中用逗号分隔行