2015-01-09 2 views
0

Честно говоря, я действительно думал, что это простая вещь. Однако моя производительность MySQL-запросов ужасающая, и я не понимаю, почему.Оптимизация запроса с несколькими объединениями

три таблицы: человек (10000000 строк), работодатель (50000 строк), person_achievements (250000 строк)

Person (indexes ix_EmpID) 
ID int (primary) 
Emp_ID int 
Full_Name varchar(250) 

Employer (indexes ix_ID (ID) and ix_SectID (Sector_ID) and ix_Name) 
ID int (primary) 
Sector_ID int 
Name varchar (250) 

person_achievements (indexes ix_ID (ID) and ix_achievement (achievement)) 
ID int 
Sect_ID 
Achievement (varchar 250) 

запрос:

select p.* 
from person p 
join employer c 
    on c.ID = p.Emp_ID 
join person_achievements a 
    on a.Sect_ID = c.Sector_ID 
where a.Achievement = 'Employee of the Month' 

Теперь я понял, что индексы я создал бы вызвать этот запрос лучше выполняет LOT. Однако это не так. Если я удалю присоединение таблицы person_achievements и сохраняю предложение where, чтобы выбрать, скажем, имя работодателя (которое также является индексированным столбцом), для создания 25 000 строк требуется чуть более секунды.

Что мне не хватает?

Edit: Добавлен человек и первичный работодатель ключи

Edit 2:

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra" 
"1","SIMPLE","a","ref","ix_SectID,ix_Achievement,ix_SectID_Achievement","ix_Achievement","253","const","12654","Using where" 
"1","SIMPLE","c","ref","PRIMARY,ix_SectID","ix_SectID","8","db.a.Sect_ID","1","" 
"1","SIMPLE","p","ref","Emp_ID","Emp_ID","9","db.c.ID","103","Using where" 
+0

Опубликовать объяснение - и надлежащие DDL не пострадают! – Strawberry

+0

Также попробуйте удалить индекс при достижении. Вместо этого наденьте его (Sect_ID, Achievement) – Strawberry

+0

Предположительно, все, что называется ID, является ПЕРВИЧНЫМ КЛЮЧОМ? – Strawberry

ответ

1

Это ваш запрос:

select p.* 
from person p join 
    employer c 
    on c.ID = p.Emp_ID join 
    person_achievements a 
    on a.Sect_ID = c.Sector_ID 
where a.Achievement = 'Employee of the Month'; 

оптимальные индексы: person_achievements(Achievement, Sect_id), employer(sector_id, emp_id), и person(emp_id).

Вы можете перестраивать внутренние соединения, так что вы можете написать запрос, как:

select p.* 
from person_achievements a join 
    employer c 
    on a.Sect_ID = c.Sector_ID join 
    person p 
    on c.ID = p.Emp_ID 
where a.Achievement = 'Employee of the Month'; 

Это должно быть, как MySQL выбирает для обработки запроса с указанными выше показателями.

Однако я не понимаю, почему таблица с именем person_achievements не имеет колонки для person_id (в данном случае Emp_Id). Что-то кажется нецелесообразным ни с структурой данных, ни с именами. Это недоразумение может быть сердцем проблемы. Если в этой таблице есть идентификатор лица, то ваше соединение может умножать количество строк, потому что оно использует неправильные ключи.

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