2015-03-31 36 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