在 SQL 中处理大量数据需要特别的方法,以防止内存溢出、锁定并确保稳定的性能。主要的方法之一是将操作拆分为批次:输入数据以小块处理,减少服务器负担,更好地控制事务和错误时的回滚。
关键方面:
ROWCOUNT 或 LIMIT / TOP)COMMIT,以减轻事务日志的负担示例 (SQL Server):
DECLARE @BatchSize INT = 1000; WHILE 1 = 1 BEGIN BEGIN TRANSACTION; DELETE TOP(@BatchSize) FROM BigLogTable WHERE CreatedDate < '2021-01-01'; IF @@ROWCOUNT = 0 BREAK; COMMIT TRANSACTION; END
如何以最小影响删除 1 亿条记录?
不正确的回答:"执行一次大的 DELETE"。
正确的回答: 分批删除(批处理),控制批次大小,在每个块后执行 COMMIT,根据需要通过延迟(WAITFOR DELAY 或类似方法)减少磁盘负担和锁定。
示例 (PostgreSQL):
DO $$ BEGIN LOOP DELETE FROM big_table WHERE created_at < NOW() - interval '1 year' LIMIT 10000; EXIT WHEN NOT FOUND; COMMIT; END LOOP; END$$;
故事
项目: 高负载银行服务。 错误: 开发人员通过一次大查询删除 8000 万行过期日志。结果 — 事务日志增长到 TB 级,耗尽所有可用磁盘空间,服务“崩溃”。
故事
项目: 电子商务平台,带有库存管理系统。 错误: 在批量插入时未限制事务大小。在导入大量批次的过程中记录出现错误,之前的所有工作都不得不回滚并重新执行,花费了几个小时而不是几分钟。
故事
项目: 零售商,订单详情报告数据库。 错误: 使用了批处理,但忽略了迭代之间的 COMMIT — 事务日志呈指数增长,服务器开始“卡顿”,然后需要紧急使用常规工具清理日志。