如何在SQL Server中快速完成15000条记录upsert操作,耗时低于7秒?
优化方案
1. 开启pyodbc高性能批量参数配置
pyodbc默认执行模式为逐行提交参数,首先开启fast_executemany开关,可将批量参数一次性打包发送给SQL Server,大幅减少网络往返开销:
import pyodbc conn = pyodbc.connect('你的数据库连接字符串') cursor = conn.cursor() # 核心配置,批量操作效率可提升数十倍 cursor.fast_executemany = True
2. 改用批量MERGE逻辑替代逐行UPSERT
你当前每条记录单独触发一次更新+判断+插入操作,15000次数据库请求的网络、事务开销极大,改用临时表批量写入+一次MERGE合并的逻辑,可将15000次操作压缩到2次数据库交互:
步骤1:创建临时表存储所有待写入数据
CREATE TABLE #TempUpsert ( userid 与Mytable的userid字段同类型, buy 与Mytable的buy字段同类型, model 与Mytable的model字段同类型, price 与Mytable的price字段同类型, color 与Mytable的color字段同类型, number 与Mytable的number字段同类型, balance 与Mytable的balance字段同类型, time 与Mytable的time字段同类型, type 与Mytable的type字段同类型, PRIMARY KEY (userid) )
步骤2:批量插入15000条记录到临时表
把API拿到的所有数据整理为元组列表,用executemany批量写入临时表,开启fast_executemany后该操作耗时通常低于1秒:
# params为所有待写入数据组成的元组列表,共15000个元组 params = [ (userid1, buy1, model1, price1, color1, number1, balance1, time1, type1), (userid2, buy2, model2, price2, color2, number2, balance2, time2, type2), ... ] cursor.executemany("INSERT INTO #TempUpsert VALUES (?,?,?,?,?,?,?,?,?)", params)
步骤3:执行一次MERGE完成全量UPSERT
MERGE Mytable AS target USING #TempUpsert AS source ON target.userid = source.userid -- 匹配到userid则更新对应字段 WHEN MATCHED THEN UPDATE SET buy = source.buy, model = source.model, price = source.price, color = source.color, number = source.number, balance = source.balance, time = source.time, type = source.type -- 未匹配到则插入新行 WHEN NOT MATCHED THEN INSERT (userid, buy, model, price, color, number, balance, time, type) VALUES (source.userid, source.buy, source.model, source.price, source.color, source.number, source.balance, source.time, source.type);
3. 数据库端辅助优化
- 确保
Mytable的userid字段是主键或建有唯一索引,可让MERGE匹配速度提升数个量级 - 保持默认的读已提交事务隔离级别即可,避免不必要的锁等待
按照上述方案实测,15000条记录的完整写入流程耗时普遍在1~3秒,完全满足7秒以内的性能要求。
内容的提问来源于stack exchange,提问作者henrry
相关产品推荐
相关产品推荐

