pyodbc 在 sp_prepexec 之后调用 sp_unprepare。这会影响参数化查询的性能吗?

Posted

技术标签:

【中文标题】pyodbc 在 sp_prepexec 之后调用 sp_unprepare。这会影响参数化查询的性能吗?【英文标题】:pyodbc calls sp_unprepare after sp_prepexec. Does that affect performance of parameterized queries? 【发布时间】:2017-03-01 02:10:21 【问题描述】:

继续

SqlAlchemy+pymssql. Will raw parametrized queries use same execution plan?

我从 pymssql 切换到 pyodbc 试图将参数化查询发送到 SQL Server。带有 Microsoft 驱动程序的 pyodbc 可以解决问题,但我觉得有些奇怪:

declare @p1 int
set @p1=6
exec sp_prepexec @p1 output,N'@P1 nvarchar(6),@P2 bigint,@P3 bigint,@P4 bigint',N'
                SELECT *
                FROM CC_sold
                WHERE id_contract =@P1
                    AND id_tip_cont=@P2
                    AND CC_sold.anul =@P3
                    AND CC_sold.luna =@P4
                ORDER BY CC_sold.anul, CC_sold.luna DESC
            ',N'176914',6,2016,9
select @p1
exec sp_unprepare 6

我的担心与这句话有关:

exec sp_unprepare 6

如果我理解正确,这将取消查询执行计划,并且我不会从查询参数化中获得任何优化。是这样吗?

【问题讨论】:

【参考方案1】:

我做了一些测试,你不必担心。当cursor 对象关闭时,pyodbc 仅发送一个sp_unprepare(用于最后执行的sp_prepexec)。也就是说,它不会发送sp_unprepare 每个 sp_prepexec

此外,实际的时序测试揭示了 pyodbc(显然可以利用缓存的执行计划)和 pymssql(显然不能)之间的性能差异。使用以下代码...

crsr = conn.cursor()
crsr.execute("DBCC FREEPROCCACHE")
if 'pyodbc' in repr(conn):
    sql = "SELECT COUNT(*) AS n FROM table1 WHERE cola=? AND colb=? AND colc=? AND cold=?"
else:
    sql = "SELECT COUNT(*) AS n FROM table1 WHERE cola=%s AND colb=%s AND colc=%s AND cold=%s"
t0 = time.time()
limit = 10
for a in range(limit):
    for b in range(limit):
        for c in range(limit):
            for d in range(limit):
                params = (a, b, c, d)
                crsr.execute(sql, params)
                n = crsr.fetchone()[0]
print(time.time() - t0)
crsr.close()
conn.close()

... 对于limit = 10,四 (4) 个嵌套的 for 循环总共运行 10,000 个查询。在我的带有本地 SQL Server 实例的 Windows 测试机器上,pymssql 需要大约 130 秒(仅 2 分钟多一点)来执行,而 pyodbc 始终在 5 秒内运行相同的代码。

【讨论】:

以上是关于pyodbc 在 sp_prepexec 之后调用 sp_unprepare。这会影响参数化查询的性能吗?的主要内容,如果未能解决你的问题,请参考以下文章

django-pyodbc 并调用存储过程

并行化 pandas pyodbc SQL 数据库调用

pyodbc - 传递参数

使用 pyodbc 将 Python 连接到 MS SQL Server

如何使用 pyodbc 执行保存在 MS Access 中的查询

PYODBC 截断 SQL Server FOR JSON 查询的响应