继续
SqlAlchemy+pymssql。原始参数化查询会使用相同的执行计划吗?
我从 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
如果我理解正确,这会取消查询执行计划,并且我不会从查询参数化中获得任何优化。是这样吗?
我做了一些测试,你不必担心。 pyodbc 只发送一个sp_unprepare
(对于最后sp_prepexec
执行)当cursor
对象已关闭。也就是说,它不sp_unprepare
every 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()
... for limit = 10
四 (4) 个嵌套for
循环总共运行 10,000 个查询。在我的具有本地 SQL Server 实例的 Windows 测试机器上,pymssql 需要大约 130 秒(仅 2 分钟多一点)执行,而 pyodbc 在 5 秒内始终运行相同的代码。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)