Diese Abfrage:
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));
Ist nur mit Indizes schwer zu optimieren. Der beste Index beginnt mit published
und dann die anderen Spalten – es ist nicht klar, wie ihre Reihenfolge sein sollte. Der Grund ist, dass alle außer published
verwenden =
nicht .
Da es sich bei Ihrem Leistungsproblem um eine Sortierung handelt, deutet dies darauf hin, dass viele Zeilen zurückgegeben werden. Typischerweise wird ein Index verwendet, um WHERE
zu erfüllen -Klausel vor dem Index kann für ORDER BY
verwendet werden . Das macht die Optimierung schwierig.
Anregungen . . . Keine ist so toll:
- Wenn Sie nach Monaten auf die Daten zugreifen möchten, sollten Sie die Daten nach Monaten partitionieren. Dadurch wird die Abfrage ohne den
ORDER BY
durchgeführt schneller, hilft aber nicht demORDER BY
. - Versuchen Sie nach
published
verschiedene Spaltenreihenfolgen im Index. Möglicherweise finden Sie die selektivste(n) Spalte(n). Aber noch einmal, das beschleunigt die Abfrage vor dem Sortieren. - Denken Sie darüber nach, wie Sie die Abfrage strukturieren können, um mehr Gleichheitsbedingungen im
WHERE
zu haben -Klausel oder um einen kleineren Datensatz zurückzugeben. - (Eigentlich nicht zu empfehlen) Setzen Sie einen Index auf
published
und die Bestellspalte. Verwenden Sie dann eine Unterabfrage, um die Daten abzurufen. Setzen Sie die Ungleichungsbedingungen (IN
usw.) in der äußeren Abfrage. Die Unterabfrage verwendet den Index zum Sortieren und filtert dann die Ergebnisse.
Letzteres wird nicht empfohlen, weil SQL (und MySQL) die Reihenfolge der Ergebnisse einer Unterabfrage nicht garantieren. Da MySQL jedoch Unterabfragen materialisiert, sind die Ergebnisse wirklich in Ordnung. Ich mag es nicht, undokumentierte Nebenwirkungen zu verwenden, die sich von Version zu Version ändern können.