Оптимизировать запрос Postgres путем индексации данных - PullRequest
0 голосов
/ 03 декабря 2018

Мое существующее приложение работает на Heroku, и я использую Postgres в качестве базы данных.

Теперь мои запросы становятся медленными из-за растущего объема данных.Вот мой запрос

SELECT *
FROM my_table
WHERE my_table.is_deleted = $1
  AND my_table.id NOT IN (SELECT my_table_user_actions.qurb_id AS my_table_user_actions_qurb_id
                          FROM my_table_user_actions
                          WHERE my_table_user_actions.user_id = $2
                            AND my_table_user_actions.is_hidden = $3)
  AND my_table.block_x BETWEEN $4 AND $5
  AND my_table.block_y BETWEEN $6 AND $7
  AND my_table.id NOT IN (SELECT sponsored_qurb_log.qurb_id AS sponsored_qurb_log_qurb_id
                          FROM sponsored_qurb_log
                          WHERE sponsored_qurb_log.qurb_id = my_table.id
                            AND sponsored_qurb_log.hash = $8
                            AND sponsored_qurb_log.user_id = $9)) AS anon_1

Этот запрос занимает почти 10 секунд для выполнения на сервере.

Теперь я готов применить индекс для следующих столбцов

  • is_deleted относится к типу boolean
  • block_x относится к типу int
  • block_y относится к типу int

Это три столбца.Здесь is_deleted всегда установлен на false, потому что я всегда хотел получить все те записи, которые не были удалены.block_x и block_y - столбцы, которые имеют широту и долготу.

Пожалуйста, дайте мне знать, что будет индекс для запроса.

Вот о чем я думаю

Индекс нескольких столбцов:

CREATE INDEX my_table_xandy_block ON my_table(blovk_x, block_y);

И частичный индекс для is_deleted:

CREATE INDEX is_deleted_index ON my_table(is_deleted) WHERE is_deleted IS FALSE;

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

1 Ответ

0 голосов
/ 03 декабря 2018

В общем случае для ответа на этот вопрос вам нужно проверить вывод EXPLAIN (ANALYZE, BUFFERS) запроса.

Но в вашем случае все просто: вам придется преобразовать предложения NOT IN в WHERE NOT EXISTS.

Пример:

WHERE a.x NOT IN (
   SELECT b.y FROM b
)

должен стать

WHERE NOT EXISTS (
   SELECT 1 FROM b
   WHERE a.x = b.y
)

Таким образом PostgreSQL может использовать «соединение» для обработки запроса, что будет быстреедля больших таблиц.

Чтобы еще больше ускорить запрос, посмотрите план выполнения и добавьте соответствующие индексы.

Если вы действительно отказываетесь переписать запрос, лучше всего сделать следующее.индексы:

CREATE INDEX ON my_table_user_actions (user_id, is_hidden);

CREATE INDEX ON sponsored_qurb_log (qurb_id, hash, user_id);
...