【发布时间】:2018-05-15 22:22:30
【问题描述】:
我有一个从本地日志读取的应用程序,该日志由每行上的 JSON 对象组成。它解析每一行并尝试插入到 SQL 服务器数据库。 SQL 服务器作为 PaaS 产品在 Azure 中运行。
我在 DB 上删除了外键以加快插入速度,但性能非常慢。
我在 python 中进行了分析,发现如下。注意执行调用,每个调用需要 60 毫秒。
Mon May 14 20:05:05 2018 logparserprof.out
385055 function calls (384911 primitive calls) in 1832.423 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
11/1 0.000 0.000 1832.423 1832.423 {built-in method builtins.exec}
1 0.000 0.000 1832.423 1832.423 logparsers.py:1(<module>)
1 0.212 0.212 1831.728 1831.728 logparsers.py:282(parse)
12796 0.030 0.000 1816.892 0.142 logparsers.py:240(parse_event)
30432 1814.571 0.060 1814.571 0.060 {method 'execute' of 'pyodbc.Cursor' objects}
12471 0.014 0.000 1796.979 0.144 logparsers.py:232(parse_event_Task)
所以我决定批量请求并看到executemany 调用并以相似的速度再次运行。 (我尝试每插入 1000-1500 条记录进行批处理)
我再次分析,executemany 花了 46 秒!
Tue May 15 00:55:46 2018 logparserprof2.out
384660 function calls (384516 primitive calls) in 1659.800 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
35 1635.272 46.722 1635.272 46.722 {method 'executemany' of 'pyodbc.Cursor' objects}
335 20.095 0.060 20.095 0.060 {method 'execute' of 'pyodbc.Cursor' objects}
我查看了 Windows 中的 resmon 以检查网络延迟,发现平均为 57-60 毫秒。
我的下一步是尝试执行多线程并尽可能为应用程序添加并行性以进行插入。但是,我想知道批量/批量插入是否可以做得更好。
我了解 MS SQL 服务器批量插入适用于 CSV 文件,这些文件必须在本地或通过 CIFS/SMB..etc 访问。
编辑 删除了关于 executemany 是简单循环的链接,因为它来自 pymssql 而不是 pyodbc。
【问题讨论】:
-
您问题中的链接指向 pymssql 代码,而不是 pyodbc 代码。 pymssql 和 pyodbc 是不同的产品。看来您确实在使用 pyodbc,但是您使用的是最新版本(当前为 4.0.23)以及
fast_executemany = True? -
@GordThompson 我明白了,谢谢。是的,我使用的是最新的,我将 fast_executemany 设置为 True,但插入速度非常慢。
-
查看您的实际代码可能会有所帮助。
-
是否可以让 SQL Profiler 向您展示服务器上发生的情况?使用
fast_executemany = False,您应该看到每个插入的单独sp_prepexec调用,但使用fast_executemany = True,您应该看到一个sp_prepare,后跟多个sp_execute调用。 -
@GordThompson 任何想法如何获取 SQL 分析器?这是 Azure 中的 SQL DB PaaS 产品。
标签: python sql-server pyodbc