我正在尝试优化超过 300 万行的单列更新。 列数据存储在 pandas dataframe 中(行 sql 索引已知) 目前我使用的代码是(使用sqlalchemy进行连接)
conn = getConnection(db).connect()
trans = conn.begin()
try:
i=0
for index, row in data.iterrows():
if not np.isnan(row[colName]):
i+=1
sql = 'update data set `{0}`= {1} where data_id={2};'.format(colName, row[colName], index)
conn.execute(sql)
if i>10000:
i = 0
trans.commit()
trans = conn.begin()
trans.commit()
except Exception as e:
trans.rollback()
conn.close()
这里是一些innodb变量
innodb_buffer_pool_size = 402653184
innodb_io_capacity = 200
由于目前我遇到了触发回滚的情况,因此如何优化此代码。
最佳答案
10K 是一个不合理的大块。
UPDATE
做了很多事情
- 解析语句并决定查询计划。
- 准备回滚(复制更新前的行);
- 更新行(读取、修改、写入);
- 将任何辅助索引更改添加到更改缓冲区,这最终需要导致写入索引。
我建议每个簇不要超过 1000 个(即每个 COMMIT
)。 1000 和 10000 之间的效率差异(假设没有超时)可能小于 1%。
当前代码每次迭代都会执行所有 4 个步骤。
建议构建一个 tmp 表,然后使用多表 UPDATE
进行更新可能会更快,也可能不会更快:
- 需要
CREATE
等临时表(一次/丛) - 插入簇的值或行。这可以(并且应该)优化为包含大量行的单个 INSERT 语句。 (我再次建议不要超过 1000 个。)如果这是“事务性”表类型,那么这里也需要考虑
ROLLBACK
。 - 您保存了#1(解析),但仍然需要为更新的每一行执行#2-4。
无论如何,这都是更多的代码。将 10000 更改为 1000 是对您的问题的简单而有效的答案。
关于python - 优化mysql多次更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50884857/