2 очень быстрых и простых запроса ужасно медленные при объединении - PullRequest
0 голосов
/ 01 июня 2018

У меня есть эти 2 таблицы.Я пытаюсь найти группы, к которым присоединился пользователь с идентификатором 1.Вот 10 строк каждой таблицы (просто чтобы показать их разметку):

PostTable (57 272 строки, идентификатор первичного ключа):

+----+---------+
| id | groupid |
+----+---------+
|  0 |       1 |
|  1 |       1 |
|  3 |       1 |
|  4 |       1 |
|  5 |       1 |
|  9 |       1 |
| 10 |       1 |
| 13 |       1 |
| 15 |       1 |
| 17 |       1 |
+----+---------+

JoinedGroupsTable (258 404 строки, уникальный идентификатор использования индекса, groupid):

+--------+---------+--------+
| id     | groupid | userid |
+--------+---------+--------+
| 258010 |       1 |      1 |
| 258484 |       6 |      1 |
|    172 |       1 |      2 |
|    173 |       2 |      2 |
|    174 |       3 |      2 |
|    175 |       4 |      2 |
|    176 |       5 |      2 |
|    177 |       6 |      2 |
|    178 |       8 |      2 |
|    179 |       9 |      2 |
+--------+---------+--------+

Когда я пытаюсь выполнить этот запрос, он завершается почти за 3 секунды, что очень медленно:

SELECT * FROM posttable p 
WHERE groupid in (SELECT groupid FROM joinedgroupstable WHERE userid=1)
ORDER BY p.ID DESC LIMIt 25;

Я также пытался использовать INNER JOIN вместоГДЕ ВХОД, но в итоге получился примерно один и тот же результат:

SELECT * FROM posttable p 
INNER JOIN joinedgroupstable jg ON userid=1 AND jg.groupid=p.groupid
ORDER BY p.ID DESC LIMIt 25;

Вот EXPLAIN SELECT для обоих запросов (одинаковый результат для обоих запросов):

|| *id* || *select_type* || *table* || *partitions* || *type* || *possible_keys* || *key* || *key_len* || *ref* || *rows* || *filtered* || *Extra* ||
|| 1 || SIMPLE || jg ||  || ref || UserID_GroupID,userid || UserID_GroupID || 4 || const || 2 || 100.00 || Using index; Using temporary; Using filesort ||
|| 1 || SIMPLE || p ||  || ref || groupid || groupid || 4 || thyra.jg.groupid || 60 || 100.00 ||  ||

Дело в том, чтоВыполнение каждого запроса само по себе очень быстро:

SELECT * FROM posttable p ORDER BY p.ID DESC LIMIt 25;

SELECT * FROM joinedgroupstable WHERE userid=1

Что может быть не так, если учесть, что каждый запрос выполняется очень быстро сам по себе, но медленно при объединении?

Ответы [ 4 ]

0 голосов
/ 01 июня 2018

Я бы использовал EXISTS вместо этого, что также могло бы быть лучше:

select p.*
from posttable p 
where exists (select 1 
              from joinedgroupstable jg
              where jg.groupid = p.groupid and jg.userid = 1
              )
order by p.id desc
limit 25;
0 голосов
/ 01 июня 2018

Другой ответ:

create index ix10 on joinedgroupstable (userid);

create index ix11 on posttable (groupid);

select p.* 
  from posttable p
  join joinedgroupstable g on p.groupid = g.groupid
  where g.userid = 1
  order by p.id desc
  limit 25;
0 голосов
/ 01 июня 2018

Если ваш вопрос упрощен, а ваш PostTable содержит больше столбцов, чем вы нам показали, ваше предложение ORDER BY ... LIMIT ... вызывает большую потерю сортировки.

Вы можете сделать так называемое "отложенное соединение"«.Сначала получите соответствующие значения идентификатора, а затем используйте их для получения строк.

select p.* 
  from posttable p
  join (
       select a.id
       from posttable a
       join joinedgroupstable g on a.groupid = g.groupid
      where g.userid = 1
      order by a.id desc
      limit 25
     ) sel on sel.id = p.id
order by p.id desc
limit 25;

Это ограничивает дорогостоящую операцию ORDER BY ... LIMIT ... только столбцом id, а затем использует выбранные значения id, чтобы попасть в вашу главную таблицу только 25 раз.

0 голосов
/ 01 июня 2018

Чтобы ускорить первый запрос, добавьте следующие индексы:

create index ix1 on joinedgroupstable (userid, groupid);

create index ix2 on PostTable (id);

Второй запрос мне кажется неправильным.

...