2010-01-22 3 views
4

Это запрос, я выполнение (без некоторых объединений, которые не относятся):MySQL GROUP BY проблемы производительности

SELECT a.*, c.id 
FROM a 
LEFT OUTER JOIN b ON a.id = b.id_anunciante 
LEFT OUTER JOIN c ON c.id = b.id_rubro 
GROUP BY a.id 

Каждая строка «а» связан с 1 до 5 строк в «б» ,

Проблема заключается в том, что GROUP BY имеет проблемы с производительностью (она занимает 10 или более раз, используя GROUP BY, а не используя ее). Мне нужно получить только одну строку каждого члена в «a».

Как это сделать быстрее?

Редактировать: Мне нужно иметь возможность фильтровать через a.id AND/OR c.id. Результат, который я должен получить, - это только 1 строка на «действительный» член «a», что означает строки, соответствующие ограничениям. Строки, не соответствующие фильтрам, не должны возвращаться. В моем первоначальном запросе, это будет сделано так:

SELECT a.*, c.id 
FROM a 
LEFT OUTER JOIN b ON a.id = b.id_anunciante 
LEFT OUTER JOIN c ON c.id = b.id_rubro 
WHERE c.id = 1 
OR a.id = 1 
GROUP BY a.id 

a.id, b.id_anunciante, b.id_rubro, c.id являются все индексы.

ответ

5
SELECT a.*, 
     (
     SELECT c.id 
     FROM b 
     JOIN с 
     ON  c.id = b.id_rubro 
     WHERE b.id_anunciante = a.id 
     -- add the ORDER BY condition to define which row will be selected. 
     LIMIT 1 
     ) 
FROM a 

Создайте индекс на b (id_anunciante), чтобы это работало быстрее.

Update:

Вам не нужен OUTER JOINs здесь.

Перепишите запрос, как это:

SELECT a.*, c.id 
FROM a 
JOIN b 
ON  b.id_anunciante = a.id 
JOIN c 
ON  c.id = b.id_rubro 
WHERE a.id = 1 
UNION ALL 
SELECT a.*, 1 
FROM a 
WHERE EXISTS 
     (
     SELECT NULL 
     FROM c 
     JOIN b 
     ON  b.id_rubro = c.id 
     WHERE c.id = 1 
       AND b.id_anunciante = a.id 
     ) 
+0

Спасибо за ваш ответ! Что делать, если мне нужно фильтровать c.id AND/OR a.id? Я не могу так поступать, не так ли? – Gerardo

+0

'@ macaco': уверенный вы можете. Просто добавьте условие 'WHERE' к внешнему запросу для фильтрации на' a' и в подзапрос для фильтрации на 'c'. – Quassnoi

+0

Я попытался фильтровать c.id в подзапросе «WHERE b.id_anunciante = a.id AND c.id = 1», но я получил такое же количество строк и те, которые не должны быть там с заполненным столбцом подзапроса с NULL. – Gerardo

0

Добавить ORDER BY NULL, чтобы избежать неявного сортировки MySQL делает при выполнении группы по.

Предположим, у вас есть индексы/PK на a.id, b.id_anunciante, b.id_rubro и c.id? Я думаю, вы могли бы попробовать добавить составной индекс в (b.id_anunciante, b.id_rubro), если ваша версия mysql не может выполнить слияние индексов.