#postgresql #caching
Вопрос:
Будучи новичком в Postgres, у меня есть вопрос относительно кэширования. Я не знаю, сколько обрабатывается базой данных, по сравнению с тем, сколько мне нужно обработать самому.
У меня есть строки, которые являются частью временного ряда. Для примера предположим, что у меня есть 1 строка каждую секунду.
Мой запрос состоит в том, чтобы получить последнюю минуту (60 строк) на скользящей основе (с настоящего момента — 1 минута до настоящего времени).
В идеале я мог бы кэшировать последний результат в клиенте и запросить последнюю секунду. К сожалению, в данных есть пробелы: некоторые строки отсутствуют и будут добавлены через несколько секунд. Так что мне все равно нужно все это опросить.
Я мог бы найти, где находятся отверстия, и сделать запрос только для них, это тоже вариант.
Мне было интересно: сколько кэширования Postgres выполняет самостоятельно?
Если у меня есть запрос, возвращающий строки 3, 4, 5, 6, а мой следующий запрос возвращает 4, 5, 6, 7. Нужно ли снова извлекать строки 4, 5, 6 или они кэшируются базой данных?
Ответ №1:
Postgres включает в себя обширную систему кэширования. Весьма вероятно, что последующие выполнения одного и того же запроса будут использовать кэшированные данные, но мы практически не влияем на это, поскольку кэш работает автономно. Что можно и нужно сделать, так это использовать подготовленные заявления. Согласно документации:
Подготовленный оператор-это объект на стороне сервера, который можно использовать для оптимизации производительности. При выполнении инструкции PREPARE указанный оператор анализируется, анализируется и переписывается. Когда впоследствии выдается команда «ВЫПОЛНИТЬ», подготовленный оператор планируется и выполняется. Такое разделение труда позволяет избежать повторяющейся работы по анализу синтаксического анализа, позволяя при этом плану выполнения зависеть от заданных значений конкретных параметров.
Однако сценарий, описанный в вопросе, предполагает совершенно другой подход к проблеме, а именно использование NOTIFY / LISTEN
функции. Вкратце:
- сервер отправляет уведомление каждый раз, когда строка вставляется в таблицу,
- приложение прослушивает согласованный канал и получает вновь введенные строки.
В этом решении приложение выполняет запрос только один раз и заполняет данные из уведомлений.
Функция запуска образца:
create or replace function before_insert_on_my_table()
returns trigger language plpgsql as $
begin
perform pg_notify('my_data', new::text);
return new;
end $;
create trigger before_insert_on_my_table
before insert on my_table
for each row execute procedure before_insert_on_my_table();
Реализация LISTEN
оператора в приложении зависит от используемого языка. Например, python psycopg2 имеет для этого удобные инструменты.
Подробнее об УВЕДОМЛЕНИИ читайте в документах.
Ответ №2:
PostgreSQL автоматически кэширует данные. Данные считываются, записываются и кэшируются в единицах 8 КБ, и всякий раз, когда вы обращаетесь к строке, блок, содержащий эту строку, будет кэшироваться.
Все, что вам нужно убедиться, — это наличие индекса на временной метке вашей таблицы, в противном случае PostgreSQL должен прочитать всю таблицу, чтобы вычислить результат. С помощью индекса он будет считывать (и кэшировать) только те блоки, которые содержат необходимые вам данные, и это ускорит ваш следующий запрос на эти данные.