Тази заявка:
SELECT *
FROM listings
WHERE (publishedon BETWEEN 1441105258 AND 1443614458) AND
(published = 1) AND
(cat_id in (1,2,3,4,5)) AND
(source_id in (1,2,3,4,5));
Трудно е да се оптимизира само с индекси. Най-добрият индекс е този, който започва с published
и след това има другите колони -- не е ясно какъв трябва да бъде редът им. Причината е, че всички освен published
не използват =
.
Тъй като вашият проблем с производителността е при сортиране, това предполага, че се връщат много редове. Обикновено индексът се използва за удовлетворяване на WHERE
клаузата преди индекса може да се използва за ORDER BY
. Това прави това трудно за оптимизиране.
Предложения. . . Никой не е толкова страхотен:
- Ако възнамерявате да осъществявате достъп до данните по месеци, можете да помислите за разделяне на данните по месеци. Това ще направи заявката без
ORDER BY
по-бързо, но няма да помогне наORDER BY
. - Опитайте различни редове на колони след
published
в индекса. Може да намерите най-селективната колона(и). Но, отново, това ускорява заявката преди сортирането. - Помислете за начини, по които можете да структурирате заявката, за да имате повече условия за равенство в
WHERE
клауза или за връщане на по-малък набор от данни. - (Наистина не се препоръчва) Поставете индекс на
published
и колоната за поръчка. След това използвайте подзаявка, за да извлечете данните. Поставете условията за неравенство (IN
и така нататък) във външната заявка. Подзаявката ще използва индекса за сортиране и след това ще филтрира резултатите.
Причината, поради която последното не се препоръчва, е, че SQL (и MySQL) не гарантират подреждането на резултатите от подзаявка. Въпреки това, тъй като MySQL материализира подзаявки, резултатите наистина са в ред. Не обичам да използвам недокументирани странични ефекти, които могат да се променят от версия на версия.