вопрос о переменных связывания postgresql - PullRequest
7 голосов
/ 24 ноября 2010

Я смотрел на вопрос и решил попробовать использовать переменные связывания.Я использую

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 ]

8 голосов
/ 24 ноября 2010

Запросы эквивалентны в Postgresql.

Bind - это оракул. При использовании он сохранит план запроса, поэтому следующее выполнение будет немного быстрее. prepare делает то же самое в Postgres.

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

psycopg2 поддерживает внутреннее связывание, а не prepare с cursor.executemany() и cursor.execute()

(Но не называйте это связыванием с людьми. Назовите это подготовкой, иначе они могут не понять, что вы имеете в виду:)

6 голосов
/ 24 ноября 2010

ВАЖНОЕ ОБНОВЛЕНИЕ : я видел исходные коды всех библиотек python для подключения к PostgreSQL через порты FreeBSD и могу сказать, что только py-postgresql действительно подготовлензаявления!Но это только Python 3+.

также py-pg_queue - забавная библиотека, реализующая официальный протокол БД (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

2 голосов
/ 24 ноября 2010

Насколько я знаю, psycopg2 никогда не поддерживал привязку параметров на стороне сервера ("переменные связывания" на языке Oracle).Текущие версии PostgreSQL поддерживают его на уровне протокола, используя подготовленные операторы, но только несколько библиотек коннекторов используют его.Postgres wiki отмечает это здесь .Вот некоторые разъемы, которые вы можете попробовать: (Я сам ими не пользовался).

Пока вы используете вызовы DB-API, вам, вероятно, следует рассмотреть cursor.executemany () вместомногократный вызов cursor.execute ().

Кроме того, привязка параметров к их запросу на сервере (а не в соединителе) не всегда будет быстрее в PostgreSQL.Примечание эта запись FAQ .

...