2015-03-31 35 views
0

我有3個表:帳戶,聯繫人和accounts_contacts(映射表)。 我在每張表中都有100萬條記錄。此查詢使用文件排序,並需要超過一分鐘,運行:如何避免使用左連接時的文件和

explain SELECT contacts.salutation salutation, contacts.first_name first_name, contacts.last_name last_name, contacts.title title, jt0_accounts.id account_id, jt0_accounts.name account_name 

FROM contacts 

LEFT JOIN accounts_contacts jt1_accounts_contacts ON (contacts.id = jt1_accounts_contacts.contact_id AND jt1_accounts_contacts.deleted = 0) 

LEFT JOIN accounts jt0_accounts ON (jt0_accounts.id = jt1_accounts_contacts.account_id AND jt0_accounts.deleted = 0) 

ORDER BY jt0_accounts.name DESC; 

這是解釋輸出:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE contacts ALL NULL NULL NULL NULL 195634 Using temporary; Using filesort 
1 SIMPLE jt1_accounts_contacts ref idx_contid_del_accid idx_contid_del_accid 113 sugar7.contacts.id,const 1 
1 SIMPLE jt0_accounts eq_ref PRIMARY,idx_accounts_id_del,idx_accounts_date_entered,idx_accnt_assigned_del PRIMARY 108 sugar7.jt1_accounts_contacts.account_id 1 

正如你所看到的,接觸表使用上的聯繫人表文件排序。

我試圖通過添加擺脫文件排序的「WHERE jt0_accounts.name <>'」前「ORDER BY」,所以它變成了:

explain SELECT contacts.salutation salutation, contacts.first_name first_name, contacts.last_name last_name, contacts.title title, jt0_accounts.id account_id, jt0_accounts.name account_name 

FROM contacts 

LEFT JOIN accounts_contacts jt1_accounts_contacts ON (contacts.id = jt1_accounts_contacts.contact_id AND jt1_accounts_contacts.deleted = 0) 

LEFT JOIN accounts jt0_accounts ON (jt0_accounts.id = jt1_accounts_contacts.account_id AND jt0_accounts.deleted = 0) 

WHERE jt0_accounts.name <> '' 
ORDER BY jt0_accounts.name DESC; 

它得到上擺脫了文件排序的聯繫人表,但它現在使用的文件排序的映射表:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE jt1_accounts_contacts ALL idx_account_contact,idx_contid_del_accid NULL NULL NULL 34994 Using where; Using temporary; Using filesort 
1 SIMPLE jt0_accounts eq_ref PRIMARY,idx_accounts_id_del,idx_accounts_date_entered,idx_accnt_name_del,idx_accnt_assigned_del PRIMARY 108 sugar7.jt1_accounts_contacts.account_id 1 Using where 
1 SIMPLE contacts eq_ref PRIMARY,idx_contacts_id_del,idx_contacts_date_entered PRIMARY 108 sugar7.jt1_accounts_contacts.contact_id 1 Using where 

的idx_account_contact指數由ACCOUNT_ID和contacts_id的。我試着將它們添加到WHERE子句中,但它似乎沒有任何區別。

任何建議,將不勝感激。 謝謝。

回答

0

對於您特別的查詢,您可能沒有太多的工作要做。但是,如果你改變使用inner join查詢,你可能有機會:

SELECT c.salutation, c.first_name, c.last_name, c.title, 
     a.id as account_id, a.name as account_name 
FROM accounts a JOIN 
    accounts_contacts ac 
    ON a.id = ac.account_id AND a.deleted = 0 
    contacts c JOIN 
    ON c.id = ac.contact_id AND ac.deleted = 0  
ORDER BY a.name DESC; 

然後,請嘗試以下指標:accounts(name, deleted, id)accounts_contacts(account_id, contact_id)concats(contact_id, deleted)

+0

除非我誤會,否則我不認爲使用內連接對我有效。因爲我想顯示聯繫人表中的所有記錄,即使它沒有關聯的帳戶。 – Formosan 2015-04-01 20:12:22

+0

@Formosan。 。 。這個版本的性能如何? – 2015-04-01 22:21:04

+0

內連接的性能很好。我可以用我最初的查詢中的「INNER」替換「LEFT」並立即得到結果。但結果不會是我所期望的。 – Formosan 2015-04-01 23:54:03