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 BYmais rápido, mas não ajudará oORDER BY. - Tente várias ordens de colunas após
publishedno í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
WHEREcláusula ou para retornar um conjunto menor de dados. - (Não recomendado) Coloque um índice em
publishede a coluna de ordenação. Em seguida, use uma subconsulta para buscar os dados. Coloque as condições de desigualdade (INe 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.