关于postgresql绑定变量的问题

时间:2010-11-24 04:40:09

标签: python postgresql psycopg2

我正在查看question并决定尝试使用绑定变量。我用

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。

3 个答案:

答案 0 :(得分:8)

查询在Postgresql中是等效的。

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

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

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

(但不要称它与pg人绑定。称之为准备,或者他们可能不知道你的意思:)。

答案 1 :(得分:6)


重要更新: 我已经看到所有python库的源代码都可以连接到FreeBSD端口的PostgreSQL,并且可以说,只有 py-postgresql 才能真正准备好语句!但它只是Python 3+。

另外py-pg_queue是实现官方数据库协议(python 2.4 +)的有趣的lib


您错过了关于准备好的语句尽可能多的使用问题的答案。 “Binded变量”是更好的形式,让我们看看:

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

等等。

<强>更新 我刚刚发现interest reciple如何透明地替换SQL查询,并使用%(name)s

答案 2 :(得分:2)

据我所知,psycopg2从未支持服务器端参数绑定(Oracle术语中的“绑定变量”)。当前版本的PostgreSQL使用预准备语句在协议级别支持它,但只有少数连接器库使用它。 Postgres维基notes this here。以下是您可能想要尝试的一些连接器:(我自己没有使用过它们。)

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

此外,在PostgreSQL中,将参数绑定到服务器中的查询(而不是连接器中)并不总是更快。注意this FAQ entry