Denna fråga:
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));
Är svårt att optimera med bara index. Det bästa indexet är ett som börjar med published
och sedan har de andra kolumnerna -- det är inte klart vad deras ordning ska vara. Anledningen är att alla utom published
använder inte =
.
Eftersom ditt prestandaproblem är ett slags, tyder det på att många rader returneras. Vanligtvis används ett index för att uppfylla WHERE
sats innan indexet kan användas för ORDER BY
. Det gör det svårt att optimera.
Förslag . . . Ingen är så bra:
- Om du ska komma åt data per månad kan du överväga att partitionera data per månad. Det kommer att göra frågan utan
ORDER BY
snabbare, men hjälper inteORDER BY
. - Testa olika ordningsföljder av kolumner efter
published
i indexet. Du kanske hittar den eller de mest selektiva kolumnerna. Men återigen snabbar detta på frågan innan sorteringen. - Tänk på hur du kan strukturera frågan för att få fler jämställdhetsvillkor i
WHERE
eller för att returnera en mindre uppsättning data. - (Rekommenderas inte riktigt) Sätt ett index på
published
och beställningskolumnen. Använd sedan en underfråga för att hämta data. Sätt ojämlikhetsvillkoren (IN
och så vidare) i den yttre frågan. Underfrågan kommer att använda indexet för att sortera och sedan filtrera resultaten.
Anledningen till att det sista inte rekommenderas är att SQL (och MySQL) inte garanterar ordningen av resultat från en underfråga. Men eftersom MySQL materialiserar delfrågor är resultaten verkligen i sin ordning. Jag gillar inte att använda odokumenterade biverkningar, som kan ändras från version till version.