Tento dotaz:
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));
Je těžké optimalizovat pouze pomocí indexů. Nejlepší index je ten, který začíná published
a pak má další sloupce -- není jasné, jaké by mělo být jejich pořadí. Důvodem je, že všechny kromě published
nepoužívají =
.
Protože váš problém s výkonem je na řazení, naznačuje to, že se vrací mnoho řádků. Obvykle se index používá k uspokojení WHERE
klauzuli před indexem lze použít pro ORDER BY
. To ztěžuje optimalizaci.
Návrhy . . . Žádný není tak skvělý:
- Pokud budete k datům přistupovat po měsících, můžete zvážit rozdělení dat podle měsíců. Tím bude dotaz bez
ORDER BY
rychlejší, ale nepomůžeORDER BY
. - Po
published
vyzkoušejte různá pořadí sloupců v indexu. Můžete najít nejselektivnější sloupce. Ale opět to urychlí dotaz před řazením. - Zamyslete se nad způsoby, jak můžete strukturovat dotaz tak, aby měl více podmínek rovnosti v
WHERE
klauzule nebo vrátit menší sadu dat. - (Opravdu se nedoporučuje) Umístěte index na
published
a sloupec objednávky. Poté použijte poddotaz k načtení dat. Vložte podmínky nerovnosti (IN
a tak dále) ve vnějším dotazu. Poddotaz použije index pro řazení a poté výsledky filtruje.
Důvod, proč se nedoporučuje, je ten, že SQL (a MySQL) nezaručují řazení výsledků z dílčího dotazu. Protože však MySQL zhmotňuje dílčí dotazy, výsledky jsou skutečně v pořádku. Nerad používám nezdokumentované vedlejší účinky, které se mohou verze od verze měnit.