使用 Execute many from pyodbc 到 SQL Server 的数据框

Posted

技术标签:

【中文标题】使用 Execute many from pyodbc 到 SQL Server 的数据框【英文标题】:Dataframe to SQL Server using Execute many from pyodbc 【发布时间】:2020-07-19 18:45:37 【问题描述】:

我正在尝试使用 Pyodbc 将数据从数据帧加载到 SQL Server,它逐行插入并且速度非常慢。

我尝试了 2 种在网上找到的方法(中等),但我没有发现性能有任何改进。

尝试在 SQL azure 中运行,因此 SQL Alchemy 不是一种简单的连接方法。请找到我遵循的方法,还有其他方法可以提高批量加载的性能。

方法一

 cursor = sql_con.cursor()
cursor.fast_executemany = True
for row_count in range(0, df.shape[0]):
  chunk = df.iloc[row_count:row_count + 1,:].values.tolist()
  tuple_of_tuples = tuple(tuple(x) for x in chunk)
  for index,row in ProductInventory.iterrows():
  cursor.executemany("INSERT INTO table ([x]],[Y]) values (?,?)",tuple_of_tuples)

方法二

 cursor = sql_con.cursor() 
for row_count in range(0, ProductInventory.shape[0]):
      chunk = ProductInventory.iloc[row_count:row_count + 1,:].values.tolist()
      tuple_of_tuples = tuple(tuple(x) for x in chunk)
  for index,row in ProductInventory.iterrows():
    cursor.executemany(""INSERT INTO table ([x]],[Y]) values (?,?)",tuple_of_tuples 

谁能告诉我为什么性能没有提高 1%?它仍然需要相同的时间

【问题讨论】:

你试过DataFrame.to_sql 使用if_exists = 'append' 参数吗? 【参考方案1】:

尝试在 SQL azure 中运行,因此 SQL Alchemy 不是一种简单的连接方法。

也许您只需要先克服这个障碍。然后你可以使用 pandas to_sql 和 fast_executemany=True。例如

from sqlalchemy import create_engine
#
# ...
#
engine = create_engine(connection_uri, fast_executemany=True)
df.to_sql("table_name", engine, if_exists="append", index=False)

如果你有一个有效的 pyodbc 连接字符串,你可以将它转换为 SQLAlchemy 连接 URI,如下所示:

connection_uri = 'mssql+pyodbc:///?odbc_connect=' + urllib.parse.quote_plus(connection_string)

【讨论】:

当我使用 sql alchemy 时,这是它抛出的错误。尝试完成交易失败。没有找到对应的交易 我无法重现您的问题。如果您需要进一步的帮助,请ask a new question,其中包括minimal reproducible example。【参考方案2】:

几件事

    为什么要对 ProductInventory 进行两次迭代?

    executemany 调用是否应该在您构建了整个 tuple_of_tuples 或其中的一批之后发生?

    pyodbc 文档说“以 fast_executemany=False 运行 executemany() 通常不会比直接运行多个 execute() 命令快得多。”因此,您需要在两个示例中设置cursor.fast_executemany=True(有关更多详细信息/示例,请参阅https://github.com/mkleehammer/pyodbc/wiki/Cursor)。我不确定为什么在示例 2 中省略了它。

这是一个示例,说明您如何完成我认为您正在尝试做的事情。 math.ceilend_idx = ... 中的条件表达式占最后一批,可能是奇数大小。因此,在下面的示例中,您有 10 行,批量大小为 3,因此最终有 4 个批次,最后一个只有 1 个元组。

import math

df = ProductInventory
batch_size = 500
num_batches = math.ceil(len(df)/batch_size)

for i in range(num_batches):
    start_idx = i * batch_size
    end_idx = len(df) if i + 1 == num_batches else start_idx + batch_size
    tuple_of_tuples = tuple(tuple(x) for x in df.iloc[start_idx:end_idx, :].values.tolist())       
    cursor.executemany("INSERT INTO table ([x]],[Y]) values (?,?)", tuple_of_tuples)

示例输出:

=== Executing: ===
df = pd.DataFrame('a': range(1,11), 'b': range(101,111))

batch_size = 3
num_batches = math.ceil(len(df)/batch_size)

for i in range(num_batches):
    start_idx = i * batch_size
    end_idx = len(df) if i + 1 == num_batches else start_idx + batch_size
    tuple_of_tuples = tuple(tuple(x) for x in df.iloc[start_idx:end_idx, :].values.tolist())
    print(tuple_of_tuples)

=== Output: ===
((1, 101), (2, 102), (3, 103))
((4, 104), (5, 105), (6, 106))
((7, 107), (8, 108), (9, 109))
((10, 110),)

【讨论】:

以上是关于使用 Execute many from pyodbc 到 SQL Server 的数据框的主要内容,如果未能解决你的问题,请参考以下文章

Python mysql executemany() and commit vs many execute() and commit

PyOD主要算法(KNN、IForest 和 MCD)的原理及使用

孤立森林(IForest)代码实现及与PyOD对比

zookeeper NIOServerCnxn: Too many connections from IP- max i

Making up VMs from Many Weak Nodes of Edge Computing

Making up VMs from Many Weak Nodes of Edge Computing