2015-03-31 2 views
0

У меня есть 3 таблицы: учетные записи, контакты и account_contacts (таблица сопоставлений). У меня есть 1 миллион записей в каждой таблице. Этот запрос использует FileSort и занимает больше минуты, чтобы запустить:Как избежать filesort при использовании левого соединения и порядка на

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 

Как вы можете видеть, таблица контактов использует FileSort на столе контактов.

Я пытался избавиться от FileSort путем добавления «ГДЕ 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; 

Это избавиться от FileSort на контакты таблицы, но теперь с помощью FileSort на таблице отображения:

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

+0

@Formosan. , , Как работает эта версия? –

+0

Производительность внутреннего соединения прекрасна. Я могу заменить «LEFT» на «INNER» в моем первоначальном запросе и получил результаты в кратчайшие сроки. Но результаты не будут такими, какие я ожидаю. – Formosan