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

看这两组所用的时间,上面似乎没有太大的时差。事实上,第二个需要更长的时间。如果我在某个地方犯了错误,有人可以纠正我吗?在这里使用 psycopg2。

4

3 回答 3

10

查询在 Postgresql 中是等效的。

Bind 是 oracle 的术语。使用时会保存查询计划,下次执行会快一点。prepare在 Postgres 中做同样的事情。

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

psycopg2 支持内部“绑定”,而不是preparecursor.executemany()cursor.execute()

(但不要称它为绑定到 pg 人。称它为准备,否则他们可能不知道你的意思:)

于 2010-11-24T05:12:34.833 回答
7

重要更新:我已经查看了所有 python 库的源代码以连接到 FreeBSD 端口中的 PostgreSQL,并且可以说,只有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))

等等。

更新: 我刚刚发现了如何用准备好的和使用 %(name)s 透明地替换 SQL 查询的兴趣

于 2010-11-24T05:13:50.180 回答
3

据我所知,psycopg2 从未支持服务器端参数绑定(Oracle 用语中的“绑定变量”)。当前版本的 PostgreSQL 确实在协议级别使用准备好的语句支持它,但只有少数连接器库使用它。Postgres wiki在此处记录了这一点。以下是您可能想尝试的一些连接器:(我自己没有使用过这些。)

只要您使用 DB-API 调用,您可能应该考虑使用 cursor.executemany() 而不是重复调用 cursor.execute()。

此外,在 PostgreSQL 中将参数绑定到它们在服务器中(而不是在连接器中)的查询并不总是更快。请注意此常见问题解答条目

于 2010-11-24T05:17:52.833 回答