2015-11-23 3 views
3

У меня есть следующие таблицы:медленных запросов Выполнение объединения нескольких таблиц

Parts 
id int (idx) 
partnumber varchar (idx) 
accountnumber (idx) 
enabled 

Образец данных: Parts

RefUserGroup 
id int (idx) 
value varchar (idx) 

Образец данных: user group

Pdf < has about 15 columns I will list ones I am interested 
in currently over 300,000's rows 
id int (idx) 
accountnumber varchar (idx) 
customername varchar (idx) 

Образец данных: pdf

Ref_UserGroup_Pdf 
id 
groupid FK (idx) 
partsnumber (idx) 
enable (idx) 

Образец данных: ref_user_group_pdf

Запрос: Это занимает около 47secs- 97 секунд для возврата данных.

SELECT p.partsnumber 
,rug.`value` AS `group` 
,pd.customername AS customer 
FROM ref_groupid_to_pdf rgp 
INNER JOIN ref_user_group rug ON rug.id = rgp.groupid 
INNER JOIN parts p on rgp.partsnumber = p.partsnumber 
LEFT JOIN pdf pd on p.accountnumber= pd.accountnumber 
WHERE rug.groupid = 2 
AND rug.groupid <> 1 
ORDER BY customer; 

Может ли кто-нибудь указать в правильном направлении, как оптимизировать этот запрос? Я знаю, что обычно мы помещаем индексы на один или несколько столбцов, но для этого я помещаю индекс в каждый столбец, но даже тогда он очень медленный.

Когда запрос присоединяется к таблице pdf, он становится очень медленным.

Update Объясните: explain

Обновлено запросов на основе предложений:

SELECT p.partsnumber 
,rug.`value` AS `group` 
,pd.customername AS customer 
FROM ref_groupid_to_pdfid rgp 
INNER JOIN ref_user_group_pdf rug ON rug.groupid = rgp.groupid 
INNER JOIN parts p on rgp.partsnumber = p.partsnumber 
INNER JOIN pdf_load pd on p.accountnumber = pd.accountnumber 
WHERE rug.id = 2 
GROUP BY rgp.partsnumber; 
+0

Что говорит 'explain select ....' вашего запроса? –

+0

Я отправлю одну секунду. – Haris

+0

@Harry Где находится 'igroupid' от ~? – Matt

ответ

1

Я бы посмотреть на имя клиента в подзапроса. В конце концов часть может иметь много записей в таблице pdf, но вы всегда заинтересованы в том, чтобы найти одну такую ​​запись произвольно. Поэтому выберите эту запись с запросом LIMIT 1.

select 
    prt.partsnumber, 
    grp.value as `group`, 
    (
    select customername 
    from pdf 
    where pdf.accountnumber = prt.accountnumber 
    limit 1 
) as customer 
from parts prt 
join ref_usergroup_pdf ref on ref.partsnumber = prt.partsnumber 
join refusergroup grp on grp.id = ref.groupid 
where ref.id = 2; 

Тот же запрос с таблицей деталей в подзапросе. Выберите какой вам больше нравится:

select 
    ref.partsnumber, 
    grp.value, 
    (
    select pdf.customername 
    from pdf 
    where pdf.accountnumber = 
    (
     select prt.accountnumber 
     from parts prt 
     where prt.partsnumber = ref.partsnumber 
    ) 
    limit 1 
) as customer 
from ref_usergroup_pdf ref 
join refusergroup grp on grp.id = ref.groupid 
where ref.id = 2; 

Как есть индекс по pdf(accountnumber), поиск должен быть довольно быстро. Это было бы еще быстрее, если бы у вас был составной индекс на pdf(accountnumber,customername), так как тогда вы получите все данные, необходимые только из индекса, и таблица не должна быть прочитана вообще.

+0

Спасибо, могу я просто указать, ref.value не существует в таблице ref_usergroup_pdf ... нам нужно присоединиться к RefUserGroup? – Haris

+1

К сожалению, вы правы. Я отредактировал свой ответ соответствующим образом, а также добавил альтернативный запрос, сделанный точно так же, только по-разному написанный. –

+0

нормально, чтобы проверить ваш запрос, я удалил нормализованную таблицу и выполнил ваш запрос wow, 0.70s !! гений, не могли бы вы просто объяснить, что вы здесь сделали, чтобы я мог понять это более подробно? – Haris

0

Попробуйте использовать подзапрос и соединить таблицу в формате PDF во внешнем запросе.

SELECT n.partsnumber, n.group, pd.customername AS customer 
FROM (SELECT p.partsnumber,rug.`value` AS `group`,p.accountnumber 
    FROM ref_groupid_to_pdf rgp 
    INNER JOIN ref_user_group rug ON rug.id = rgp.groupid 
    INNER JOIN parts p on rgp.partsnumber = p.partsnumber 
    WHERE rug.groupid = 2 
    AND rug.groupid <> 1) n 
LEFT JOIN pdf pd on n.accountnumber= pd.accountnumber ORDER BY customer; 
+0

спасибо, я получаю следующую ошибку: [Err] 1054 - Неизвестный столбец «клиент» в разделе «order» – Haris

+0

Извините, переместите заказ по внешнему запросу. Я буду обновлять свой ответ – olkid

+0

Если вам нужно предложение group by, поместите его во внутренний запрос до ") n" – olkid

1

Использование STRAIGHT_JOIN, чтобы уменьшить время запроса:

SELECT STRAIGHT_JOIN p.partsnumber 
,rug.`value` AS `group` 
,pd.customername AS customer 
FROM ref_groupid_to_pdf rgp 
INNER JOIN ref_user_group rug ON rug.id = rgp.groupid 
INNER JOIN parts p on rgp.partsnumber = p.partsnumber 
LEFT JOIN pdf pd on p.accountnumber= pd.accountnumber 
WHERE rug.groupid = 2 
AND rug.groupid <> 1 
ORDER BY customer; 
+0

Спасибо, я попробовал ваш запрос, и он принимает 50.637s для выполнения ... – Haris

+0

Итак, тогда попробуйте дать индексирование по id, groupid, partsnumber, accountnumber. – RJParikh

+0

Если вы использовали индексирование, попробуйте один раз с FORCE INDEX. Это будет определенно полезно в вашем запросе. – RJParikh

Смежные вопросы