#python #postgresql #sqlalchemy
#python #postgresql #sqlalchemy
Вопрос:
У меня есть приложение, которое отображает содержимое базы данных, которая обновляется каждые 5-10 минут. Загрузка всех данных в базу данных занимает около 5 минут. Вместо того, чтобы перезагружать все данные в базе данных при каждом обновлении, я хотел бы загружать только новые строки или поля строк, которые были обновлены.
- Можно ли проверить наличие измененных или новых полей с помощью sqlalchemy (для опроса изменений)?
- Возможно ли дождаться измененных или новых полей с помощью sqlalchemy (с вызовом блокирующей функции)?
База данных — это база данных postgres, если это имеет значение.
Ответ №1:
В ProstgeSQL есть механизм NOTIFY / LISTEN, который можно использовать с триггерами для отправки уведомлений о вставке, удалении и обновлении. Уведомление включает в себя аргумент, такой как таблица и действие.
Не похоже, что SQLAlchemy поддерживает эту функциональность, вероятно, поскольку это не стандарт SQL, а специфичный для Postgres.
Вот пример проверки изменений в базе данных prostgres с помощью NOTIFY / LISTEN с использованием python: PostgreSQL ПРОСЛУШИВАЕТ / УВЕДОМЛЯЕТ
Поиск в Google NOTIFY in PostgreSQL and python
может предоставить дополнительную помощь.
Ответ №2:
SQLAlchemy напрямую не поддерживает ПРОСЛУШИВАНИЕ / УВЕДОМЛЕНИЕ Postgres, но вы можете получить доступ к нему через psycopg2, что затем дает вам такую возможность: http://initd.org/psycopg/docs/advanced.html#async-notify
(Я понял это из этой сути: https://gist.github.com/dtheodor/3862093af36a1aeb8104 )
Psycopg2 может выполнять полностью асинхронную доставку уведомлений. Лично мне не очень повезло с этим внутри SQLAlchemy, и я подозреваю, что это слишком низкий уровень для их поддержки. Однако в документах приведен приведенный ниже пример, в котором используется select() для ожидания, пока соединение сообщит, что что-то происходит, а затем использует poll(), чтобы узнать, есть ли уведомление.
import select
import psycopg2
import psycopg2.extensions
conn = psycopg2.connect(DSN)
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
curs = conn.cursor()
curs.execute("LISTEN test;")
print "Waiting for notifications on channel 'test'"
while 1:
if select.select([conn],[],[],5) == ([],[],[]):
print "Timeout"
else:
conn.poll()
while conn.notifies:
notify = conn.notifies.pop(0)
print "Got NOTIFY:", notify.pid, notify.channel, notify.payload
Этот пример имеет необязательный 5-секундный тайм-аут, но иногда этот тайм-аут довольно удобен для одновременной проверки некоторых других вещей.
Один из таких вариантов использования — когда вы используете NOTIFY, чтобы сообщить вам об обновляемой таблице. Вы устанавливаете время ожидания на что-то довольно долгое. Если вы получаете УВЕДОМЛЕНИЕ или тайм-аут, вы делаете ВЫБОР, чтобы увидеть, что изменилось в таблице. Таким образом, вы сделаете это сразу, если получите УВЕДОМЛЕНИЕ, но в конечном итоге сделаете это в любом случае, даже если вы этого не сделаете.