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
相关产品推荐
相关产品推荐

