To zapytanie:
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));
Trudno go zoptymalizować za pomocą samych indeksów. Najlepszy indeks to taki, który zaczyna się od published
a następnie ma inne kolumny — nie jest jasne, jaka powinna być ich kolejność. Powodem jest to, że wszystkie oprócz published
nie używasz =
.
Ponieważ twój problem z wydajnością jest w pewnym sensie, sugeruje to, że zwracanych jest wiele wierszy. Zazwyczaj indeks jest używany do spełnienia WHERE
klauzula przed indeksem może być użyta dla ORDER BY
. To utrudnia optymalizację.
Propozycje . . . Żaden nie jest taki wspaniały:
- Jeśli zamierzasz uzyskiwać dostęp do danych według miesiąca, możesz rozważyć podział danych według miesiąca. Spowoduje to, że zapytanie bez
ORDER BY
szybciej, ale nie pomożeORDER BY
. - Wypróbuj różne kolejności kolumn po
published
w indeksie. Możesz znaleźć najbardziej selektywne kolumny. Ale po raz kolejny przyspiesza to zapytanie przed sortowaniem. - Zastanów się, w jaki sposób możesz ustrukturyzować zapytanie, aby zawierało więcej warunków równości w
WHERE
klauzulę lub zwrócić mniejszy zestaw danych. - (Niezalecane) Umieść indeks na
published
i kolumna zamawiania. Następnie użyj podzapytania, aby pobrać dane. Umieść warunki nierówności (IN
i tak dalej) w zewnętrznym zapytaniu. Podzapytanie użyje indeksu do sortowania, a następnie przefiltruje wyniki.
Powodem, dla którego to ostatnie nie jest zalecane, jest to, że SQL (i MySQL) nie gwarantuje kolejności wyników z podzapytania. Jednakże, ponieważ MySQL materializuje podzapytania, wyniki są naprawdę w porządku. Nie lubię używać nieudokumentowanych efektów ubocznych, które mogą się zmieniać z wersji na wersję.