Questa domanda:
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));
È difficile da ottimizzare con solo indici. L'indice migliore è quello che inizia con published
e poi ha le altre colonne -- non è chiaro quale dovrebbe essere il loro ordine. Il motivo è perché tutti tranne published
non stanno usando =
.
Poiché il tuo problema di prestazioni è su un ordinamento, ciò suggerisce che vengono restituite molte righe. Tipicamente, un indice viene utilizzato per soddisfare il WHERE
clausola prima che l'indice possa essere utilizzato per ORDER BY
. Ciò rende difficile l'ottimizzazione.
Suggerimenti. . . Nessuno è così eccezionale:
- Se hai intenzione di accedere ai dati per mese, potresti prendere in considerazione la possibilità di partizionare i dati per mese. Ciò renderà la query senza
ORDER BY
più veloce, ma non aiuterà ilORDER BY
. - Prova vari ordini di colonne dopo la
published
nell'indice. Potresti trovare le colonne più selettive. Ma, ancora una volta, questo velocizza la query prima dell'ordinamento. - Pensa ai modi in cui puoi strutturare la query in modo da avere più condizioni di uguaglianza nel
WHERE
clausola o per restituire un insieme di dati più piccolo. - (Non proprio consigliato) Metti un indice su
published
e la colonna di ordinazione. Quindi utilizzare una sottoquery per recuperare i dati. Inserisci le condizioni di disuguaglianza (IN
e così via) nella query esterna. La sottoquery utilizzerà l'indice per l'ordinamento e quindi filtrerà i risultati.
Il motivo per cui l'ultimo non è raccomandato è perché SQL (e MySQL) non garantiscono l'ordinamento dei risultati da una sottoquery. Tuttavia, poiché MySQL materializza le sottoquery, i risultati sono davvero in ordine. Non mi piace usare effetti collaterali non documentati, che possono cambiare da versione a versione.