2016-10-19 14 views
2

pyodbcはsp_prepexecの後にsp_unprepareを呼び出します。これはパラメータ化されたクエリのパフォーマンスに影響しますか?

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

の継続で、私は、SQL Serverに送信パラメータ化クエリを取得しようとしましたpyodbcするpymssqlから切り替えます。マイクロソフトのドライバと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 [email protected] 
        AND [email protected] 
        AND CC_sold.anul [email protected] 
        AND CC_sold.luna [email protected] 
       ORDER BY CC_sold.anul, CC_sold.luna DESC 
      ',N'176914',6,2016,9 
select @p1 
exec sp_unprepare 6 

私の心配は、このステートメントに関連しています

exec sp_unprepare 6 

私は右理解していれば、これは、クエリ実行プランをキャンセルし、私は意志クエリのパラメータ化から最適化を得ることはできません。それは事実ですか?

答えて

3

私は少しのテストをしましたが、気にする必要はありません。 pyodbcは、cursorオブジェクトが閉じられているときに、sp_unprepare(最後にsp_prepexecが実行されたとき)の1つだけを送信します。つまり、sp_unprepare毎にsp_prepexecを送信しません。

さらに、実際のタイミングテストでは、pyodbc(キャッシュされた実行計画を利用できるように見える)とpymssql(明らかにできない)のパフォーマンスの違いがわかります。次のコードで... limit = 10 4(4)ネストされたループのfor

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() 

は...万個のクエリの合計を実行します。ローカルのSQL Serverインスタンスを持つ私のWindowsテストマシンでは、pymssqlは約130秒(わずか2分)を実行しますが、pyodbcは5秒以内に同じコードを一貫して実行します。

関連する問題