pyodbc вызывает sp_unprepare после sp_prepexec. Влияет ли это на производительность параметризованных запросов?
В продолжение
SQLAlchemy + pymssql. Будут ли необработанные параметризованные запросы использовать тот же план выполнения?
Я переключился с pymssql на pyodbc и попытался получить параметризованные запросы, отправленные на SQL Server. pyodbc с драйвером Microsoft делает свое дело, но что-то кажется мне странным:
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 ответ
Я провел небольшое тестирование, и вам не нужно беспокоиться. pyodbc отправляет только один sp_unprepare
(за последние sp_prepexec
выполнено), когда cursor
объект закрыт. То есть это не 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
циклы запускают в общей сложности 10000 запросов. На моей тестовой машине Windows с локальным экземпляром SQL Server выполнение pymssql занимает около 130 секунд (чуть более 2 минут), в то время как pyodbc последовательно выполняет один и тот же код менее чем за 5 секунд.