Как оптимизировать запрос SQL SELECT для создания ленты новостей пользователя? - PullRequest
1 голос
/ 08 февраля 2020

В настоящее время я пытаюсь создать функцию для создания новостной ленты пользователя, используя следующий запрос из таблицы posts. Это оператор SQL, который мы используем:

SELECT *
FROM "posts" AS "post"
WHERE "post"."sourceId" IN (...)
ORDER BY "post"."createdAt" DESC, "post"."timestamp" DESC
LIMIT 10;

Таблица posts в настоящее время имеет примерно 200K + строк и, вероятно, будет расти намного больше. Мои навыки работы с БД не самые сильные, но есть ли способ оптимизировать этот запрос, чтобы он выполнялся максимально быстро? Я предполагаю, что недостаточно добавить индекс для столбца sourceId, но вместо этого потребуется индекс из нескольких столбцов, чтобы также учитывать столбец ORDER BY.

Ответы [ 2 ]

1 голос
/ 08 февраля 2020

Для этого запроса:

SELECT p.*
FROM posts p
WHERE p.sourceId IN (...)
ORDER BY p.createdAt DESC, p.timestamp DESC
LIMIT 10;

Единственный индекс, который действительно может помочь, это индекс posts(sourceId).

Обратите внимание, что я удалил ". Не экранируйте имена таблиц и столбцов при их определении. Тогда вам не нужно избегать их при использовании.

Однако запрос все равно должен отсортировать все данные. И это может занять много времени. Более сложный запрос легче оптимизировать на Postgres:

select p.*
from ((select p.*
       from posts p
       where sourceId = $si_1
       order by p.createdAt desc, p.timestamp desc
       limit 10
      ) union all
      (select p.*
       from posts p
       where sourceId = $si_2
       order by p.createdAt desc, p.timestamp desc
       limit 10
      ) union all
      . . .
    ) p
order by p.createdAt desc, p.timestamp desc;

Этот запрос может использовать индекс на posts(sourceId, createdAt desc, timestamp desc) для внутренних выборок. Это должно быть быстро. внешний order by все еще нуждается в сортировке, но объем данных должен быть намного меньше.

Например, если типичный источник имеет 10000 строк, а вы ищете только 3 из них, то ваша версия запрос должен отсортировать 30 000 строк, чтобы получить 10. Эта версия выбирает 30 строк, использует индекс и затем сортирует их, чтобы получить окончательные значения 10.

Это было бы большой разницей в производительности.

0 голосов
/ 08 февраля 2020

Вы можете обнаружить, что достаточно только индекса на sourceId:

CREATE INDEX src_idx ON posts (sourceId);

Postgres затем придется вручную отсортировать записи, которые выходят за предложение WHERE. Дальнейшее добавление столбцов в предложении ORDER BY также может помочь:

CREATE INDEX idx ON posts (sourceId, createdAt DESC, timestamp DESC);

Это может ускорить операцию сортировки, позволяя Postgres сортировать совпадающие группы записей sourceId сразу.

...