Denne forespørgsel:
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));
Er svært at optimere med kun indekser. Det bedste indeks er et, der starter med published
og så har de andre kolonner -- det er ikke klart, hvad deres rækkefølge skal være. Årsagen er, at alle undtagen published
bruger ikke =
.
Fordi dit præstationsproblem er en slags, tyder det på, at mange rækker bliver returneret. Typisk bruges et indeks til at opfylde WHERE
klausul før indekset kan bruges til ORDER BY
. Det gør det svært at optimere.
Forslag . . . Ingen er så gode:
- Hvis du vil have adgang til dataene efter måned, kan du overveje at opdele dataene efter måned. Det vil gøre forespørgslen uden
ORDER BY
hurtigere, men hjælper ikkeORDER BY
. - Prøv forskellige rækkefølger af kolonner efter
published
i indekset. Du finder måske den eller de mest selektive kolonner. Men igen, dette fremskynder forespørgslen før sorteringen. - Tænk på måder, hvorpå du kan strukturere forespørgslen for at have flere lighedsbetingelser i
WHERE
klausul eller for at returnere et mindre sæt data. - (Virkelig ikke anbefalet) Sæt et indeks på
published
og bestillingskolonnen. Brug derefter en underforespørgsel til at hente dataene. Sæt ulighedsbetingelserne (IN
og så videre) i den ydre forespørgsel. Underforespørgslen vil bruge indekset til at sortere og derefter filtrere resultaterne.
Grunden til, at det sidste ikke anbefales, er fordi SQL (og MySQL) ikke garanterer rækkefølgen af resultater fra en underforespørgsel. Men fordi MySQL materialiserer underforespørgsler, er resultaterne virkelig i orden. Jeg kan ikke lide at bruge udokumenterede bivirkninger, som kan ændre sig fra version til version.