SQL объединяет, подсчитывает () и группирует, сортируя «посты» по количеству голосов «да» / «нет» - PullRequest
0 голосов
/ 18 ноября 2009

У меня есть posts, votes и comments таблицы. Каждый пост может иметь N голосов «да», N голосов «нет» и N комментариев. Я пытаюсь отсортировать сообщения по количеству голосов "за".

У меня есть запрос, который делает именно это, но выполняется слишком медленно. На наборе данных из 1500 сообщений и 15K голосов это займет 48 секунд на моем компьютере разработчика. Как я могу оптимизировать это?

select
  p.*,
  v.yes,
  x.no
from
  posts p
left join (select post_id, vote_type_id, count(1) as yes from votes where (vote_type_id = 1) group by post_id) v on v.post_id = p.id
left join (select post_id, vote_type_id, count(1) as no from votes where (vote_type_id = 2) group by post_id) x on x.post_id = p.id
left join (select post_id, count(1) as comment_count from comments group by post_id) p on p.confession_id = p.id
order by
  yes desc
limit
    0, 10

EDIT:

  • Votes и Comments оба имеют post_id FK
  • Добавление индекса на vote_type_id и post_id в таблицу votes сбрасывает .1sec от выполнения запроса.

Ответы [ 4 ]

0 голосов
/ 19 ноября 2009

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

Во-вторых, вы присоединяетесь к votes дважды: один раз за нет и один раз за да. Используя оператор CASE, вы можете вычислить суммы обоих значений за одно соединение. Вот пример запроса:

select
  p.*,
  sum(case when v.vote_type_id = 1 then 1 else 0 end) as yes,
  sum(case when v.vote_type_id = 2 then 1 else 0 end) as no,
  count(c.id) as comment_count
from posts p
left join votes v on v.post_id = p.id
left join comments c on c.post_id = p.id
order by yes desc
limit 0, 10

В-третьих, вы можете убедиться, что существуют правильные внешние ключи для отношений между сообщениями, голосами и комментариями. Также может помочь индекс (post_id, vote_type_id) на votes.

0 голосов
/ 18 ноября 2009

Используйте explain для проверки плана выполнения запроса, чтобы вы могли понять, почему он медленный, обычно этого достаточно, чтобы увидеть план, а затем создать соответствующие индексы. Таблицы 1.5k и 15k действительно очень малы, поэтому запрос должен выполняться намного быстрее.

0 голосов
/ 18 ноября 2009

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

Если я неправильно понял вашу базу данных или вы не можете ее изменить, по крайней мере, у вас есть внешний ключ для voices.post_id для post.id? Внешние ключи имеют решающее значение, если вы присоединяетесь.

0 голосов
/ 18 ноября 2009

Добавьте столбец «yes_count» и используйте триггер, чтобы обновлять счетчик голосов для каждого поста после проведения голосования. Вы можете проиндексировать этот столбец, тогда он должен быть очень быстрым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...