2015-01-09 180 views
0

老實說,我真的認爲這是一件簡單的事情。然而,我的MySQL查詢性能是可怕的,我不知道爲什麼。通過多個連接優化查詢

三個表:人(10,000,000行),僱主(50,000行),person_achievements(250,000行)

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行。

我錯過了什麼?

編輯:添加人員和僱主的主鍵

編輯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

後解釋 - 和正確的DDLs不會傷害! – Strawberry

+0

另外,嘗試刪除成就指數。相反,把它放在(Sect_ID,Achievement) – Strawberry

+0

大概所有叫做ID的都是PRIMARY KEY? – 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)的列。數據結構或命名似乎有些不妥。這種誤解可能是問題的核心。如果該表中存在人員ID,那麼您的連接可能會乘以行數,因爲它使用了錯誤的鍵。