PostgreSQL: форсировать данные в память

32

Существует ли систематический способ заставить PostgreSQL загрузить определенную таблицу в память или хотя бы прочитать ее с диска, чтобы она была кэширована системой?

Адам Матан
источник

Ответы:

25

Вы можете быть заинтересованы в одной из тем списков рассылки , на которую отвечает Том Лейн (основной разработчик):

[..] Но я считаю, что люди, которые думают, что они умнее алгоритма кэширования LRU, обычно ошибаются. Если таблица используется очень интенсивно, она просто останется в памяти. Если он не используется достаточно интенсивно, чтобы оставаться в памяти в соответствии с алгоритмом LRU, возможно, пространство памяти действительно должно быть потрачено на что-то другое. [..]

Вы также можете быть заинтересованы в SO вопросе: https://stackoverflow.com/questions/486154/postgresql-teilitary-tables и, возможно, более удобные https://stackoverflow.com/questions/407006/need-to-load-the -whole-PostgreSQL-базы данных в самом баран

DrColossos
источник
1
+1 Та же идея относится и к другим СУБД.
GBN
25
Да и нет. Мы блокируем некоторые таблицы Oracle в памяти, потому что знаем, что они могут использоваться не так часто, но в ситуации, когда они используются, задержка будет убийственной. БД всегда должна давать последнее слово БД (другой пример - подсказка оптимизатора запросов).
Гай
35

В Postgres 9.4 наконец-то добавлено расширение для предварительной загрузки данных из отношений в ОС или буферный кеш базы данных (на ваш выбор):

pg_prewarm

Это позволяет быстрее достичь полной производительности.

Запустите один раз в вашей базе данных (подробные инструкции здесь ):

CREATE EXTENSION pg_prewarm;

Тогда просто предварительно загрузить любое данное отношение. Основной пример:

SELECT pg_prewarm('my_tbl');

Находит первую таблицу с именем my_tblв пути поиска и загружает ее в буферный кеш Postgres

Или:

SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');

prefetchвыдает асинхронные запросы предварительной выборки в операционную систему, если это поддерживается, или выдает ошибку в противном случае. read читает запрошенный диапазон блоков; в отличие от prefetchэтого, это синхронно и поддерживается на всех платформах и сборках, но может быть медленнее. bufferсчитывает запрошенный диапазон блоков в буферный кеш базы данных

По умолчанию bufferиспользуется наибольшее влияние (более высокая стоимость, лучший эффект).

Прочитайте руководство для более подробной информации , цитаты оттуда.
Депеш тоже писал об этом.

Эрвин Брандштеттер
источник
4

В общем случае, если у вас достаточно ОЗУ, вы, как правило, можете доверять службе базы данных, чтобы хорошо хранить вещи, которые вы регулярно используете в ОЗУ. Некоторые системы позволяют намекать, что таблица всегда должна храниться в оперативной памяти (что полезно для небольших таблиц, которые не используются часто, но при их использовании важно, чтобы они отвечали как можно быстрее), но если pgsql имеет такие табличные подсказки вы должны быть очень осторожны при их использовании, так как вы уменьшаете объем памяти, доступной для кэширования чего-либо еще, чтобы вы могли замедлить работу вашего приложения в целом.

Если вы хотите заполнить кеш страниц базы данных при запуске (например, после перезагрузки или другой операции сопровождения, которая заставляет БД забыть обо всем, что кэшируется), тогда напишите сценарий, который выполняет следующее:

SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>

(последний шаг повторяется для каждого индекса или курса, и соблюдайте осторожность, чтобы поля в предложении ORDER BY располагались в правильном порядке)

После выполнения вышеуказанного все данные и страница индекса должны быть прочитаны, и поэтому они будут находиться в кеше страницы ОЗУ (по крайней мере, на данный момент) У нас есть подобные сценарии для наших баз данных приложений, которые запускаются после перезагрузки, так что первые пользователи, входящие в систему впоследствии, не испытывают более медленной реакции. Вам лучше писать вручную любой такой сценарий, а не сканировать таблицы определения БД (например, sys.objects/ sys.indexes/ sys.columnsв MSSQL), тогда вы можете выборочно сканировать наиболее часто используемые индексы, а не сканировать все, что займет больше времени.

Дэвид Спиллетт
источник
3
Это не будет работать, по крайней мере, на PostgreSQL. Небольшой (256 КБ) кольцевой буфер выделяется из общих буферов для последовательного сканирования, чтобы предотвратить использование всего буферного кэша. См. Github.com/postgres/postgres/blob/master/src/backend/storage/… для подробностей. Вы можете проверить это, выполнив SELECT * из большой таблицы, а затем просмотрев таблицу pg_buffercache (из расширения pg_buffercache).
14:09
@hbn привет, но этот парень из этой ветки
scythargon
@scythargon может оказаться в кеше ОС, но не попадет в буферный кеш PostgreSQL. Попробуйте то, что я предложил выше, если вы мне не верите.
HBN
В Postgres 9.5 я пытался SELECT * FROM schema.tableи увидел, как он загружает всю таблицу 60 ГБ в мой буферный кеш 100GiB PostgreSQL.
Судо
1

У меня была похожая проблема:
после перезапуска службы сервера и отбрасывания всех кэшированных данных, многие запросы, вызываемые впервые, были действительно очень медленными, вызывая особую сложность запросов, пока все необходимые индексы и данные не были кэшированы. это означает, что, например, пользователи должны нажимать один раз на каждый «элемент» (время выполнения 1-3 секунды) и связанные данные из 50 миллионов строк, чтобы пользователи больше не испытывали никаких нежелательных задержек. Первые 3 часа пользователи испытывают навязчивые зависания, до тех пор, пока большинство используемых данных не кэшируются, а программы не достигают высочайшего уровня с производственной производительностью, а заканчиваются даже тогда, 2 дня - несколько внезапных коротких задержек, когда достигается меньшее количество обращающихся к ним данных в первый раз ... , для статистических данных и т. д.

Чтобы решить эту проблему, мы написали небольшой скрипт на python, который выполняет выборки для самых тяжелых таблиц с большими индексами. Это заняло 15 минут, и никаких задержек в производительности.

LongBeard_Boldy
источник
0

Хм, может быть, команда COPY поможет. Просто выполните COPY для stdout и прочитайте его. Это можно сделать с помощью pg_dump:

pg_dump -U <user> -t <table> <database> > /dev/null

Другой способ - найти все файлы таблиц и запустить cat <files> > /dev/null.

Вот пример того, как получить имена файлов таблиц:

# SELECT oid, datname FROM pg_database ;
  oid  |  datname  
-------+-----------                                                                                                                                          
<...>
 16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
  oid  | relname 
-------+---------
 24576 | fn
(1 row)
-- oid of our table is 24576

Итак, файл (ы) таблицы: / path / to / pgsql / data / base / 16384/24576 *

Вы хотите также прочитать индексы и таблицы тостов, получить их oids таким же образом.

Кстати, зачем тебе это? Я считаю, что postgresql и ОС достаточно умны, чтобы кэшировать самые горячие данные и поддерживать их в хорошем состоянии. эффективность кеша.

RVS
источник
0

Я использую RAMDrive из QSoft, который был протестированным как самым быстрым псевдодиск для Windows. Я просто использовал

initdb -D e:\data

где e: \ - это место RamDisk.

Дэвид
источник
5
PG на Windows - довольно смелый выбор для рабочего сайта, поскольку в Windows он работает намного медленнее, чем в * nix (независимо от оперативной памяти).
DrColossos