使用fast_executemany Python pyodbc

时间:2018-01-22 13:11:43

标签: python sql-server python-3.x pypyodbc

我正在尝试将.csv文件中包含的数据从我的电脑插入到远程服务器。这些值将插入包含3列的表中,即TimestampValueTimeseriesID。我必须一次插入大约3000行,因此我目前正在使用pyodbcexecutemany

到目前为止,我的代码如下所示:

with contextlib.closing(pyodbc.connect(connection_string, autocommit=True)) as conn:
    with contextlib.closing(conn.cursor()) as cursor:
        cursor.fast_executemany = True  # new in pyodbc 4.0.19

            # Innsert values in the DataTable table
            insert_df = df[["Time (UTC)", column]]
            insert_df["id"] = timeseriesID
            insert_df = insert_df[["id", "Time (UTC)", column]]
            sql = "INSERT INTO %s (%s, %s, %s)  VALUES (?, ?, ?)" % (
                sqltbl_datatable, 'TimeseriesId', 'DateTime', 'Value')

            params = [i.tolist() for i in insert_df.values]
            cursor.executemany(sql, params)

当我使用pyodbc 4.0.19时,我将fast_executemany选项设置为True,这应该可以加快速度。但是,出于某种原因,当我启用fast_executemany选项时,我没有看到任何重大改进。有没有其他方法可以用来加速我的文件插入?

此外,关于上面显示的代码的性能,我注意到当禁用autocommit=True选项时,而我在数据末尾包含cursor.commit()命令的速度明显加快了。是否有任何具体原因导致我不知道这种情况发生?

非常感谢任何帮助:)

1 个答案:

答案 0 :(得分:2)

关于您注意到的cursor.commit()加速:当您使用autocommit=True时,您要求代码为每个插入执行一个数据库事务。这意味着只有在数据库确认数据存储在磁盘上后,代码才会恢复。在大量cursor.commit()之后使用INSERT时,您实际上正在执行一个数据库事务,并且数据在临时存储在RAM中(可能会写入磁盘,但在您指示时不是全部用于完成交易的数据库。)

完成事务的过程通常需要更新磁盘上的表,更新索引,刷新日志,同步副本等,这是昂贵的。这就是为什么你在你描述的两个场景之间观察到这样的加速。 如果以更快的方式运行,请注意,在执行cursor.commit()之前,您无法100%确定数据是否在数据库中,因此可能需要在出现错误时重新发出查询(任何部分事务将被回滚)。