优化mysql多个更新

时间:2018-06-16 04:07:05

标签: python mysql sqlalchemy sql-update innodb

我正在尝试针对超过3M行优化单个列的更新。 列数据存储在pandas数据帧中(行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

如何优化此代码,因为目前我遇到了回滚被攻击的时间。

1 个答案:

答案 0 :(得分:0)

10K是一个不合理的大块。

UPDATE做很多事情

  1. 解析该语句并确定查询计划。
  2. 准备回滚(复制更新之前的行);
  3. 更新行(读取,修改,写入);
  4. 将所有辅助索引更改添加到更改缓冲区,最终将需要导致对索引的写入。

我建议每个团块(即每个COMMIT)的数量不要超过1000。 1000和10000之间的效率差异(假设没有超时)可能小于1%。

当前代码为每次迭代执行所有4个步骤。

建议先建立一个tmp表,然后使用多表UPDATE进行更新,可能会或不会会更快:

  • 需要CREATE等临时表(一次/成簇)
  • 插入丛集的值或行。可以(并且应该)将此优化为具有许多行的单个INSERT语句。 (同样,我建议不要超过1000。)如果这是“事务”表类型,那么这里也有ROLLBACK注意事项。
  • 您保存了#1(解析),但仍必须对更新的每一行执行#2-4。

无论如何,这是很多代码。将10000更改为1000是您问题的简单有效答案。