sql >> Databáze >  >> RDS >> Mysql

Při objednávání podle data desc, použití dočasného zpomaluje dotaz

Myslím, že většina problémů zde a v podobných otázkách pochází z nepochopení toho, jak MySQL (a další databáze) používá indexy pro řazení. Odpověď zní:MySQL nepoužívá indexy pro řazení, pouze umí číst data v pořadí indexu nebo v opačném směru. Pokud jste náhodou chtěli, aby byla data seřazena v pořadí aktuálně používaného indexu - máte štěstí, jinak bude výsledek seřazen (proto filesort in EXPLAIN)

To je pořadí celého výsledku většinou závisí na tom, která tabulka byla první ve spojení. A když se podíváte na svůj EXPLAIN, uvidíte, že spojení začíná od tabulky 'log_codes' (protože je mnohem menší).

V zásadě potřebujete složený index (partner_id, datum) na 'log_entries', krycí složený index (log_code, category_overview, log_desc) pro 'log_codes', změňte 'INNER JOIN' na 'STRAIGHT_JOIN', abyste vynutili objednávku spojení, a seřaďte podle 'date' DESC (tento index bude naštěstí také pokrývat).

UPD1 :Omlouvám se, špatně jsem zadal index pro první tabulku:měl by být (partner_id, log_code, date) .

MySQL může buď přímo vydávat data, pokud souhlasíte s pořadím, ve kterém je získává, nebo vkládat data do dočasné tabulky, poté použít třídění a výstup. Když objednáváte podle pole z jakékoli jiné než první tabulky ve spojeních, musí MySQL třídit data (nejen výstup v pořadí podle indexu) a k řazení dat potřebuje dočasnou tabulku.

Pro výstup řádků 50000,25 MySQL stejně potřebuje načíst prvních 50000 a přeskočit je. Protože jsem vynechal sloupec v indexu, MySQL nejenom prohledala index, ale pro každou položku provedla další vyhledávání na disku pro log_code hodnota. S krycím indexem by to mělo být mnohem rychlejší, protože všechna data lze načíst z indexu.

UPD2 :zkuste vynutit index:

SELECT log_entries.date, log_codes.log_desc
FROM log_entries FORCE INDEX (IX_partner_code_date)
STRAIGHT_JOIN log_codes
  ON log_codes.log_code = log_entries.log_code
WHERE log_entries.partner_id = 1
  AND log_codes.category_overview = 1
ORDER BY log_entries.date DESC;


  1. Co je transakce.commit() v režimu spánku?

  2. VYBERTE * KDE NEEXISTUJE

  3. 4 způsoby, jak zabránit přetížení výstrah pomocí monitorování serveru SQL

  4. Jaký je rozdíl mezi typy řetězců VARCHAR(255) a TINYTEXT v MySQL?