MySQL COUNT нескольких левых соединений - оптомизация - PullRequest
1 голос
/ 16 декабря 2011

У меня есть запрос, который получает счетчики из нескольких таблиц, используя LEFT JOIN и подзапросы. Идея состоит в том, чтобы подсчитать различные активности, в которых участвовал участник.

Схема выглядит следующим образом:

член PK member_id

table1 ПК tbl1_id FK member_id

table2 ПК tbl2_id FK member_id

Таблица3 ПК tbl3_id FK member_id

Мой запрос выглядит так:

SELECT t1.num1,t2.num2,t3.num3
FROM member m
LEFT JOIN
(
   SELECT member_id,COUNT(*) as num1
   FROM table1
   GROUP BY member_id
) t1 ON t1.member_id = m.member_id
LEFT JOIN
(
   SELECT member_id,COUNT(*) as num2
   FROM table2
   GROUP BY member_id
) t2 ON t2.member_id = m.member_id
LEFT JOIN
(
   SELECT member_id,COUNT(*) as num3
   FROM table3
   GROUP BY member_id
) t3 ON t3.member_id = m.member_id
WHERE m.member_id = 27

Где 27 - идентификатор теста. Фактический запрос объединяет более трех таблиц, и запрос выполняется несколько раз с изменением member_id. Проблема в том, что этот запрос выполняется довольно медленно. Я получаю информацию, которая мне нужна, но мне интересно, кто-нибудь может предложить способ оптимизировать это. Любой совет очень ценится. Большое спасибо.

Ответы [ 3 ]

3 голосов
/ 16 декабря 2011

Вы должны рефакторинг вашего запроса. Вы можете сделать это, изменив порядок сбора данных в запросе. Как?

  • Сначала примените предложение WHERE
  • Применить СОЕДИНЕНИЯ в последний раз

Вот ваш оригинальный запрос:

SELECT t1.num1,t2.num2,t3.num3 
FROM member m 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num1 
   FROM table1 
   GROUP BY member_id 
) t1 ON t1.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num2 
   FROM table2 
   GROUP BY member_id 
) t2 ON t2.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num3 
   FROM table3 
   GROUP BY member_id 
) t3 ON t3.member_id = m.member_id 
WHERE m.member_id = 27 

Вот вам новый запрос

SELECT
   IFNULL(t1.num1,0) num1,
   IFNULL(t1.num2,0) num2,
   IFNULL(t1.num3,0) num3
FROM
(
   SELECT * FROM member m 
   WHERE member_id = 27
) 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num1 
   FROM table1 
   WHERE member_id = 27
   GROUP BY member_id 
) t1 ON t1.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num2 
   FROM table2 
   WHERE member_id = 27
   GROUP BY member_id 
) t2 ON t2.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num3 
   FROM table3 
   WHERE member_id = 27
   GROUP BY member_id 
) t3 ON t3.member_id = m.member_id 
;

Кстати, я изменил member m на SELECT * FROM member m WHERE member_id = 27 на случай, если вам понадобится какая-либо информация об элементе 27. Я также добавил функцию IFNULL к каждому результату, чтобы получить 0, если счетчик равен NULL.

Вы должны быть абсолютно уверены,

  • member_id является первичным ключом таблицы элементов
  • member_id индексируется в таблицах table1, table2 и table3

Попробуй !!!

2 голосов
/ 16 декабря 2011

Не зная вашей схемы и того, что вы сделали для индексов, один ВОЗМОЖНЫЙ способ сделать это быстрее:

SELECT (select ifnull(count(*),0) from table1 where table1.member_id = m.id) as num1,
 (select ifnull(count(*),0) from table2 where table2.member_id = m.id) as num2,
 (select ifnull(count(*),0) from table3 where table3.member_id = m.id) as num3
from member m
WHERE m.member_id = 27

Теперь, это немного рискованная рекомендация, просто потому что я не знаючто-нибудь о вашей БД или о том, что еще работает, или где узкие места.

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

0 голосов
/ 17 декабря 2011
SELECT num1, num2, count(*) as num3
FROM (
  SELECT member_id, num1, count(*) as num2
  FROM (
    SELECT member_id, count(*) as num1
    FROM member
    LEFT JOIN  table1 USING (member_id)
    WHERE member_id = 27) as m1
  LEFT JOIN table2 USING (member_id)) as m2
LEFT JOIN table3 USING (member_id);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...