10

私は質問を見ていて、バインド変数を使用してみることにしました。私が使う

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セットの所要時間を見ると、あまり時間差がないように見えます。実際、2 番目の方が時間がかかります。どこかで間違いを犯した場合、誰かが私を修正できますか? ここでpsycopg2を使用しています。

4

3 に答える 3

10

クエリは Postgresql と同等です。

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

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

psycopg2 は、andではなくprepare、内部の「バインド」をサポートしますcursor.executemany()cursor.execute()

(しかし、それを pg people への bind と呼ばないでください。prepare と呼ばないと、彼らはあなたが何を意味するのか分からないかもしれません:)

于 2010-11-24T05:12:34.833 に答える
7

重要な更新: FreeBSD ポートで PostgreSQL に接続するためのすべての Python ライブラリのソースを調べたところ、 py-postgresqlだけが実際に準備されたステートメントを実行すると言えます。ただし、Python 3+ のみです。

また、py-pg_queue は、公式の DB プロトコルを実装する面白いライブラリです (python 2.4+)


できるだけ多く使用する準備済みステートメントに関するその質問に対する答えを逃しました。「バインドされた変数」はこれのより良い形式です。見てみましょう:

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

したがって、テストは次のようになります。

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 クエリを準備済みで %(name)s を使用して透過的に置き換える方法の興味のレシピ を見つけました

于 2010-11-24T05:13:50.180 に答える
3

私の知る限り、psycopg2 はサーバー側のパラメーター バインディング (Oracle 用語では「バインド変数」) をサポートしていません。PostgreSQL の現在のバージョンは、準備されたステートメントを使用してプロトコル レベルでそれをサポートしていますが、少数のコネクタ ライブラリのみがそれを利用しています。Postgres wikiはこれをここに記しています。試してみたいと思われるいくつかのコネクタを次に示します (私はこれらを自分で使用したことはありません)。

DB-API 呼び出しを使用している限り、cursor.execute() を繰り返し呼び出す代わりに、cursor.executemany() を検討する必要があります。

また、(コネクタではなく) サーバーでパラメーターをクエリにバインドすると、PostgreSQL で常に高速になるとは限りません。この FAQ エントリに注意してください。

于 2010-11-24T05:17:52.833 に答える