2010-11-24 42 views
5

私はquestionを見ていて、バインド変数を使用しようと決めました。多くの時間差がないように思えるの上に私は、二組のために要した時間を見てみるとpostgresqlのバインド変数に関する質問

sql = 'insert into abc2 (interfield,textfield) values (%s,%s)' 
a = time.time() 
for i in range(10000): 
    #just a wrapper around cursor.execute 
    db.executeUpdateCommand(sql,(i,'test')) 

db.commit() 

sql = 'insert into abc2 (intfield,textfield) values (%(x)s,%(y)s)' 
for i in range(10000): 
    db.executeUpdateCommand(sql,{'x':i,'y':'test'}) 

db.commit() 

を使用しています。実際には、2番目の方法は時間がかかります。私がどこかでミスをした場合、誰かが私を正すことができますか?ここでpsycopg2を使用します。

答えて

7

クエリはPostgreSQLで同等です。

バインドはオラクル用語である。これを使用すると、クエリプランが保存され、次の実行が少し速くなります。 prepareはPostgresで同じことをします。

http://www.postgresql.org/docs/current/static/sql-prepare.html

psycopg2は、内部の「バインド」をサポートしていないpreparecursor.executemany()cursor.execute()

(としかし、それは人々をPGに結合し呼び出すことはありません。準備それを呼び出すか、彼らはあなたが何を意味するか知らないかもしれません:)

5

重要UPDATE:私はトンを接続するために、すべてのPythonライブラリのソースに見てきました o PostgreSQLをFreeBSDポートに入れて、py-postgresqlしか実際の準備文を出さないと言うことができます!しかし、それはPython 3+のみです。

もPY-pg_queueは、あなたが、できるだけ多くを使用するために準備された文について、その質問に対しての答えを逃してきた


(2.4+のpython)公式DBプロトコルを実装libに面白いです。 "バインドさ変数は" こののより良い形です、見てみましょう:

sql = 'insert into abc2 (intfield, textfield) values (:x , :y)' 
for i in range (10000): 
    cur.execute(sql, x=i, y='test') 

またはこの:

def _data(n): 
    for i in range (n): 
     yield (i, 'test') 
sql = 'insert into abc2 (intfield, textfield) values (? , ?)'  
cur.executemany(sql, _data(10000)) 

など

sql_q = 'insert into abc (intfield, textfield) values (?, ?)' # common form 
sql_b = 'insert into abc2 (intfield, textfield) values (:x , :y)' # should have driver and db support 

ので、あなたのテストはこれでなければなりません。

UPDATE: 私はちょうど透過%の準備として、使用してSQLクエリを交換するinterest reciple方法を発見した(名)■

+0

@ Eir、私はpsycopg2でバインド変数は%(name)sのように指定されていると思いますか? – goh

+0

私はこの形式のSQLで非常に注意を払い、実際には本番環境では使用しません。 –

+0

少なくとも%(name)s –

2

は、私の知る限りでは、psycopg2は、サーバー側のパラメータをサポートしたことはありませんバインディング(Oracleの用語では「バインド変数」)。現在のバージョンのPostgreSQLではプリペアドステートメントを使用してプロトコルレベルでサポートしていますが、ごく一部のコネクタライブラリでのみ使用できます。 Postgres wiki notes this here。いくつかのコネクタを試してみてください。(私はこれを自分で使っていません。)

限り、あなたはDB-APIの呼び出しを使用しているとして、あなたはおそらく(cursor.executemanyを検討するべきである)の代わりに繰り返しカーソルを呼び出します。 execute()。

また、(コネクタではなく)サーバのクエリへのバインディングパラメータがPostgreSQLで常に高速になるとは限りません。注this FAQ entry

+0

cursor.executemany()はpyscopg2のために 'bind'ですhttp://initd.org/psycopg/docs/cursor.html#cursor.executemany –

+0

あなたはそう思いますが、ソースコードを見ると、 psycopg2はexecute()とexecutemany()に同じコードを使用します。ステートメントを準備してバインディングのためにサーバーに送信するのではなく、ライブラリー内で独自のパラメーター・バインディングを行います。 –

+0

したがって、psycopg2のexecutemany()は、Pythonインタプリタに何度も切り替えるのではなく、コンパイルされたコードを残してexecute()よりもわずかに速いかもしれませんが、Oracleの用語 "bind variables"を使用するときには、 –