新人求助--大表全表更新

【TiDB 使用环境】生产环境
【TiDB 版本】7.5.2
【部署方式】机器部署
【操作系统/CPU 架构/芯片详情】红帽X86因特尔,128C 256G
【机器部署详情】pd3+tidb3+tikv3 ,监控都部署在第一台机器上
【集群数据量】20T
【集群节点数】3
【问题复现路径】生产有一张大表,数据量在8-900w,表只有一个主键id,但是不是有序递增,现在需要更新一个字段,涉及范围是将近800w条数据,除了通过脚本使用多批次小批量更新的办法外,有其他更好的办法(和研发确认过,后续数据量上涨也有可能还会有这样的操作)

个人认为没有其他方案。

谢谢分享
我在其他类型的数据库上也是分批,而且我看他产品文档上也是推荐分批更新,只是不清楚TIDB这边有没有什么自定义的功能之类的方案或者参数,所以求助下,看看大家是不是有不同方向的建议

TiDB 没有 Oracle 式在线并行更新语法,生产标准方案依旧是分批迭代更新,没有内置一键批量更新命令。

非事务语句可以自动拆分,但是呢,保证不了事务

800w行在TiDB里不算大表,但全表更新确实要注意热点和事务大小。建议直接分批UPDATE,每批5000-10000行,用主键范围切分,配合WHERE id BETWEEN x AND y,避免全表扫描。脚本里加个并发控制,比如4-8个并发,别打爆TiKV。

如果字段更新逻辑简单(比如固定值或简单计算),可以试试用tiup bench或pt-archiver这类工具生成批量任务,比手写脚本稳。另外,更新前确认下GC和region分布,必要时先split region分散热点。

大表近全量更新优先按主键区间小批量提交,控制事务大小与 TiKV 写压力;可评估生成新表+导入切换,或按业务拆批错峰。避免单事务更新近 800 万行。

1 个赞

把一条大 update,TiDB 内部自动拆成若干小事务,每批 N 行,自动提交,自动重试可重试冲突错误,不生成超大事务。

可以直接用 TiDB 7.5 的非事务 DML 来做批量更新,比如:

BATCH ON id LIMIT 50000 UPDATE 表名 SET 字段=新值 WHERE 条件;

TiDB 会按 id 自动拆成多个小事务执行,不需要自己写脚本循环。id 不要求连续,只要是有索引的列即可,主键最合适。

批大小一般从 5 万起步,根据实际写入压力再调整。可以先用 DRY RUN 看拆分效果:

BATCH ON id LIMIT 50000 DRY RUN UPDATE ...

注意几点:

  • 这是非事务 DML,批次之间不回滚
  • 建议保证更新逻辑幂等
  • 执行期间尽量避免其他写入冲突

如果类似大批量更新比较频繁,直接固定用 BATCH 会比脚本更省事;建新表再切换虽然也能做,但整体复杂度更高。WHERE 条件如果后续变细粒度,记得关注索引是否匹配。

1 个赞

建议分批次更新,可加临时索引,避开业务高峰,控制事务大小防 region 热点。

刷的字段是同一个值吗?是的话,可以考虑把字段删掉,再添加个带默认值的列回来。

手动编写脚本分批更新,或者使用7.5内置的BATCH语法