编程 千万级数据的全表更新的正确方式

2024-11-19 01:43:51 +0800 CST views 1294

千万级数据的全表更新的正确方式

在处理业务迭代时,有时候需要对MySQL表中的数据进行全表更新。当数据量较小时(万级别),可以直接执行SQL语句,但当数据量达到亿级别时,问题随之而来。尤其是主从架构的MySQL数据库,在进行主从同步时会依赖binlog,其格式如下:

  • Statement: 记录主库上执行的每一条SQL,日志量较小,但一些函数(如random)可能会出现问题。
  • Row: 记录每条数据被修改或删除的详细信息,日志量较大。
  • Mixed: 混合使用statementrow两种方式,常规SQL使用statement,其他复杂SQL使用row

如果在亿级数据表上执行全表update,将产生大量binlog,会导致主库负载剧增,并影响主从同步的性能。因此,直接执行全表update并不可行。

直接update带来的问题

例如,某次需要将用户的基本信息中的HTTP链接转换为HTTPS,涉及到上千万条记录,初步尝试了直接执行以下SQL:

update tb_user_info set user_img = replace(user_img, 'http://', 'https://');

这种方式生成的binlog对主库和从库都会带来巨大的压力。

深度分页问题

为避免这种压力,可以通过分批处理来更新数据。常见的方式是使用limit分页:

update tb_user_info set user_img = replace(user_img, 'http://', 'https://') limit 1, 1000;

然而,MySQL的limit操作在分页较深时效率会急剧下降,原因是MySQL需要从B+树的叶子节点开始进行遍历,导致性能问题。

in操作的低效

另一种常见方法是将待更新的id查询出来,再通过in批量更新:

select * from tb_user_info where id > {index} limit 100;
update tb_user_info set user_img = replace(user_img, 'http', 'https') where id in ({id1, id2, id3});

虽然MySQL对in操作有一定的优化,但在面对大量数据时,效率依然不理想。

解决方案:分批更新与索引优化

经过与DBA的多次沟通,最终确定了以下的优化策略:

  1. 使用/*!40001 SQL_NO_CACHE */语法来避免缓存,防止本次查询影响buffer pool
  2. 强制使用主键索引FORCE INDEX(PRIMARY),并按主键顺序进行排序。
  3. 分批更新数据,使用已排序的主键范围进行批量更新。

优化后的SQL示例如下:

select /*!40001 SQL_NO_CACHE */ id from tb_user_info FORCE INDEX(`PRIMARY`) where id > "1" ORDER BY id limit 1000,1;
update tb_user_info set user_img = replace(user_img, 'http', 'https') where id > "{1}" and id < "{2}";

通过这种方式,可以避免影响缓存数据,同时对数据库主从同步的性能产生较小影响。在执行批量更新时,可以通过接口来控制更新速率,动态调整刷库的速度,以保障数据库的正常运行。

其他注意事项

如果业务使用UUID作为主键而非自增ID,数据的顺序性将无法保证。对此,建议在数据入库时提前处理,代码上线后再进行全量数据更新。

通过这些优化措施,可以有效地解决千万级数据表的全表更新问题。

复制全文 生成海报 数据库 性能 优化 MySQL 数据处理

推荐文章

使用Python实现邮件自动化
2024-11-18 20:18:14 +0800 CST
Vue中如何使用API发送异步请求?
2024-11-19 10:04:27 +0800 CST
前端代码规范 - Commit 提交规范
2024-11-18 10:18:08 +0800 CST
Python上下文管理器:with语句
2024-11-19 06:25:31 +0800 CST
# 解决 MySQL 经常断开重连的问题
2024-11-19 04:50:20 +0800 CST
Vue3中如何进行性能优化?
2024-11-17 22:52:59 +0800 CST
Go语言中实现RSA加密与解密
2024-11-18 01:49:30 +0800 CST
10个极其有用的前端库
2024-11-19 09:41:20 +0800 CST
liunx宝塔php7.3安装mongodb扩展
2024-11-17 11:56:14 +0800 CST
php使用文件锁解决少量并发问题
2024-11-17 05:07:57 +0800 CST
五个有趣且实用的Python实例
2024-11-19 07:32:35 +0800 CST
Go语言中的`Ring`循环链表结构
2024-11-19 00:00:46 +0800 CST
JavaScript设计模式:单例模式
2024-11-18 10:57:41 +0800 CST
Plyr.js 播放器介绍
2024-11-18 12:39:35 +0800 CST
jQuery `$.extend()` 用法总结
2024-11-19 02:12:45 +0800 CST
Python Invoke:强大的自动化任务库
2024-11-18 14:05:40 +0800 CST
PHP来做一个短网址(短链接)服务
2024-11-17 22:18:37 +0800 CST
vue打包后如何进行调试错误
2024-11-17 18:20:37 +0800 CST
使用 Git 制作升级包
2024-11-19 02:19:48 +0800 CST
FastAPI 入门指南
2024-11-19 08:51:54 +0800 CST
程序员茄子在线接单