У нас есть прерывистые медленные запросы. Наш PostgreSQL борется с памятью? - PullRequest
1 голос
/ 05 ноября 2019

Я исследую несколько медленных запросов, и мне нужна помощь в чтении полученных данных.

У нас есть один конкретный запрос, который использует индекс и в большинстве случаев выполняется довольно быстро, однако время от временивремя, которое оно работает медленно (700 мс +), не знаю почему.

Limit  (cost=8.59..8.60 rows=1 width=619) (actual time=5.653..5.654 rows=1 loops=1)
   ->  Sort  (cost=8.59..8.60 rows=1 width=619) (actual time=5.652..5.652 rows=1 loops=1)
         Sort Key: is_main DESC, id
         Sort Method: quicksort  Memory: 25kB
         ->  Index Scan using index_pictures_on_imageable_id_and_imageable_type on pictures  (cost=0.56..8.58
rows=1 width=619) (actual time=3.644..5.587 rows=1 loops=1)
               Index Cond: ((imageable_id = 12345) AND ((imageable_type)::text = 'Product'::text))
               Filter: (tag = 30)
               Rows Removed by Filter: 2
 Planning Time: 1.699 ms
 Execution Time: 5.764 ms

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

Я начал думать, что, возможно, наш экземпляр не может сохранить весь индекс в памяти, поэтому он использует диск время от временико времени. Это объясняет медленные запросы. Тем не менее, это над моей головой. Имеет ли это смысл?

В этой таблице около 15 миллионов строк и 5156 MB по размеру. Индекс 1752 MB. Кстати, это индекс btree.

Наш PostgreSQL находится на «высокодоступном» экземпляре Google Cloud SQL. Он имеет 2 виртуальных ЦП и 7,5 ГБ оперативной памяти. Вся наша база данных имеет размер около 35 ГБ.

Потребление ЦП практически никогда не превышает 40%. Обычно он составляет около 20-30%.

Проверяя график памяти экземпляра, я заметил, что потребление увеличивается до ~ 4 ГБ, затем оно падает до ~ 700 МБ и снова начинает расти. Это повторяющийся паттерн.

Теоретически, экземпляр имеет 7,5 ГБ ОЗУ, но я не знаю, предполагается ли все это доступно для PostgreSQL. В любом случае, ~ 3,5 ГБ только для ОС звучит довольно высоко, верно?

График памяти

Я прочитал, что эти настройки важны, поэтому выкидываю их сюда (Cloud SQL по умолчанию):

shared_buffers                             | 318976
temp_buffers                               | 1024
work_mem                                   | 4096

Учитывая, что у нас есть куча других таблиц и индексов, разумно ли предположить, что если один только индекс равен 1,7 ГБ, то 7,5 ГБ для всего экземпляра слишком мало?

Можно ли как-то утверждать, есть ли у нас проблемы с памятью или нет?

Я ценю вашу помощь.

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

Три вещи, которые могут вам помочь:

  1. Эта функция делает «предварительный прогрев» таблицы над вашей памятью. Это значительно снижает доступ к диску, что значительно повышает производительность. Ограничением для предварительного подогрева являются ресурсы. Таким образом, не все таблицы могут быть помещены в память. Если таблица небольшая или к ней нет постоянного доступа, это не рекомендуется. Каждый раз, когда ваша база данных останавливается, при следующем запуске базы данных вам нужно снова запускать pg_prewarm()

https://www.postgresql.org/docs/9.4/pgprewarm.html

Создайте кластер в вашем индексе. Вы можете создать один кластер для каждой таблицы. Кластеризация вашего индекса - это отличный способ получить хороший доступ к данным. Способ хранения данных связан с кластером, поэтому доступ к определенной позиции по ранее упорядоченным данным происходит очень быстро.

CLUSTER [VERBOSE] имя_таблицы [USING index_name]

Ссылка: https://www.postgresql.org/docs/current/sql-cluster.html

Периодически запускать VACUUM ANALYZE на столе. Postgresql собирает статистику о ваших запросах и классифицирует информацию в вакууме с возможностью анализа, ориентированной на оптимизацию ваших запросов.
0 голосов
/ 08 ноября 2019

Я думаю, что это больше проблема с памятью, как вы говорите. Проверяя ваш график, я могу сказать, что большую часть времени ваша база данных использует 4 ГБ выделенной памяти, и при запуске запроса postgres должен использовать диск.

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

Вы можете изменить свою память, назначенную postgres , настраивая флаги , в частности флаг work_mem. Я предлагаю выделить 2 ГБ дополнительной памяти и проверить результаты. Если вы видите, что ваша база данных снова использует 100% памяти, рассмотрите возможность увеличения всей памяти и памяти, выделенной базе данных.

...