Посмотрим.
- Адреса: 22 271
- Контакты: 17,906
- Организации: 8 246
обращается к контактам LEFT JOIN c дает около 20 000 * 20 000 ~ 400 миллионов сравнений для приблизительно 20 000 результатов
LEFT JOIN организации дают около 10 000 * 20 000 ~ 200 миллионов сравнений для примерно 20 000 результатов
, который мы сортируем в основном по контактным строкам, затем отбрасываем все, кроме 24 из них. Кажется, различимость адресов имеет минимальное значение.
Так как мы в основном сортируем по контактам, как насчет подвыбора по контактам, сохраняя
несколько больше (скажем, в 4 раза), чем нам нужно:
SELECT * FROM contacts ORDER BY last_name, first_name LIMIT 100
Тогда присоединяй их к их адресам, сохраняя первые сотни или около того
SELECT a.*
FROM (SELECT * FROM contacts ORDER BY last_name, first_name LIMIT 0, 100) AS c
LEFT JOIN addresses a
ON c.id = a.contact_id
LIMIT 0, 100
Затем присоединитесь к этим организациям
SELECT *
FROM (
SELECT *
FROM (SELECT * FROM contacts ORDER BY last_name, first_name LIMIT 0, 100) AS c
LEFT JOIN addresses a
ON c.id = a.contact_id
LIMIT 0, 100
) AS ca LEFT JOIN organizations o
ON o.id = ca.organization_id
ORDER BY ca.last_name, ca.first_name, o.name
LIMIT 0, 24
Я уверен, что синтаксис облажан, но я также уверен, что принцип сокращения результатов, установленных на каждом этапе, указывает на поучительный путь. Я, вероятно, тоже сделал пару компромиссов, так что результат близко приближается к 10-секундному ответу, но гораздо быстрее.