У меня есть 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, но, похоже, это не имеет никакого значения.
Любое предложение будет оценено. Спасибо.
Если я ошибаюсь, я не думаю, что для меня используется внутреннее соединение. Потому что я хочу показать все записи из таблицы контактов, даже если у нее нет связанных аккаунтов. – Formosan
@Formosan. , , Как работает эта версия? –
Производительность внутреннего соединения прекрасна. Я могу заменить «LEFT» на «INNER» в моем первоначальном запросе и получил результаты в кратчайшие сроки. Но результаты не будут такими, какие я ожидаю. – Formosan