кэширование строк с помощью Postgres

#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 должен прочитать всю таблицу, чтобы вычислить результат. С помощью индекса он будет считывать (и кэшировать) только те блоки, которые содержат необходимые вам данные, и это ускорит ваш следующий запрос на эти данные.