You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sqlite3 executemany执行DELETE过慢,千万级数据场景求优化建议

针对批量删除慢的优化方案

首先得揪出你当前代码慢的核心原因:用executemany执行一万次单独的DELETE语句,相当于让数据库做一万次全表扫描(如果orderid没索引的话),这反复遍历1200万条数据的操作,耗时超1小时完全在情理之中。下面给你几个实用的优化方向,按见效快慢排序:

1. 给orderid加索引(最基础也最立竿见影)

如果rawdata表还没给orderid创建索引,这绝对是第一优先级要做的事。没有索引时,每次删除都要遍历整张表找匹配的orderid,一万次下来的开销可想而知。

-- 根据你的orderid实际类型调整,比如INT/VARCHAR
CREATE INDEX idx_rawdata_orderid ON rawdata(orderid);

小贴士:建索引会增加日常插入/更新的微小开销,但对于你这种每日批量删除+插入的场景,索引带来的删除速度提升远大于这点额外开销。

2. 改用批量删除逻辑,避免逐条操作

把一万个orderid一次性交给数据库处理,让它只做一次扫描就能完成所有删除,而不是一万次。这里有两种常用方式:

方式A:临时表关联删除(兼容性强,适合大数量场景)

先把要删除的orderid存入临时表,再通过表关联完成批量删除:

# 1. 创建临时表(不同数据库语法略有差异,比如MySQL用TEMPORARY TABLE,PostgreSQL用CREATE TEMP TABLE)
cursor.execute("""CREATE TEMPORARY TABLE temp_orderids (orderid INT PRIMARY KEY);""")  # 替换成你的orderid类型

# 2. 批量插入要删除的orderid
unique_orderids = [(x,) for x in data_update["orderid"].unique()]
cursor.executemany("""INSERT INTO temp_orderids (orderid) VALUES (?);""", unique_orderids)

# 3. 关联删除(不同数据库写法可优化,比如MySQL用JOIN效率更高)
# 通用写法
cursor.execute("""DELETE FROM rawdata WHERE orderid IN (SELECT orderid FROM temp_orderids);""")
# MySQL优化写法
# cursor.execute("""DELETE r FROM rawdata r JOIN temp_orderids t ON r.orderid = t.orderid;""")

方式B:直接用IN子句(轻量快捷,适合数量不超数据库限制的场景)

把所有orderid拼成一个IN列表,一次执行删除语句:

unique_orderids = data_update["orderid"].unique()
# 根据数据库类型生成占位符:MySQL用%s,SQLite用?,PostgreSQL用%s
placeholders = ", ".join(["%s"] * len(unique_orderids))
delete_query = f"""DELETE FROM rawdata WHERE orderid IN ({placeholders});"""
cursor.execute(delete_query, tuple(unique_orderids))

注意:部分数据库对IN子句的参数数量有上限(比如MySQL默认是1000),如果你的orderid数量超过限制,可以拆分批次,比如每500个执行一次删除。

3. 利用数据库专属优化特性

不同数据库有自己的批量删除优化手段,比如:

  • PostgreSQL:用USING子句关联删除,效率比IN子句更高:
    DELETE FROM rawdata USING temp_orderids WHERE rawdata.orderid = temp_orderids.orderid;
    
  • SQL Server:可以用DELETE FROM ... FROM语法关联临时表完成删除;
  • MySQL:可以适当调大bulk_insert_buffer_size参数优化批量插入临时表的速度,但核心还是索引+批量删除逻辑。

4. 长期优化:分区表重构(适合有规律的删除场景)

如果你的orderid带有时间或分组规律(比如按日期前缀生成),可以把rawdata表改成按orderid分区的表。这样删除某个分区内的所有记录几乎是瞬间完成的,但这个需要调整表结构,属于架构级优化,适合长期规划。

最后提醒:所有优化操作请先在测试环境验证,避免影响生产数据。

内容的提问来源于stack exchange,提问作者chris_monaut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:46:18