Esta consulta:
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));
É difícil otimizar apenas com índices. O melhor índice é aquele que começa com
published
e então tem as outras colunas -- não está claro qual deve ser a ordem delas. A razão é porque todos, exceto published
não está usando =
. Como seu problema de desempenho está em uma classificação, isso sugere que muitas linhas estão sendo retornadas. Normalmente, um índice é usado para satisfazer o
WHERE
cláusula antes que o índice possa ser usado para o ORDER BY
. Isso torna isso difícil de otimizar. Sugestões. . . Nenhum é tão bom:
- Se você for acessar os dados por mês, considere particionar os dados por mês. Isso fará a consulta sem o
ORDER BY
mais rápido, mas não ajudará oORDER BY
. - Tente várias ordens de colunas após
published
no índice. Você pode encontrar a(s) coluna(s) mais seletiva(s). Mas, mais uma vez, isso acelera a consulta antes da classificação. - Pense em maneiras de estruturar a consulta para ter mais condições de igualdade no
WHERE
cláusula ou para retornar um conjunto menor de dados. - (Não recomendado) Coloque um índice em
published
e a coluna de ordenação. Em seguida, use uma subconsulta para buscar os dados. Coloque as condições de desigualdade (IN
e assim por diante) na consulta externa. A subconsulta usará o índice para classificar e filtrar os resultados.
A razão pela qual o último não é recomendado é porque SQL (e MySQL) não garantem a ordenação dos resultados de uma subconsulta. No entanto, como o MySQL materializa subconsultas, os resultados realmente estão em ordem. Eu não gosto de usar efeitos colaterais não documentados, que podem mudar de versão para versão.