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

mysql:velmi jednoduché SELECT id ORDER BY LIMIT nebude používat INDEX podle očekávání (?!)

Indexové vyhledávání jsou podle hodnoty , nikoli podle pozice . Index může vyhledat hodnotu 2955900, ale na to se neptáte. Žádáte, aby dotaz začínal na offsetu 2955900. řádku v tabulce.

Optimalizátor nemůže předpokládat, že všechny hodnoty primárního klíče jsou po sobě jdoucí. Je tedy dost pravděpodobné, že 2955900. řádek má mnohem vyšší hodnotu.

I když jsou hodnoty primárního klíče po sobě jdoucí, můžete mít podmínku WHERE, která odpovídá například pouze 45 % řádků. V takovém případě by hodnota id na 2955900. řádku byla způsob za hodnotou id 2955900.

Jinými slovy, vyhledávání indexu s hodnotou id 2955900 nezobrazí 2955900. řádek.

MySQL tedy nemůže použít index pro posun limitu. musí skenujte řádky a spočtěte je, dokud nedosáhne offset+limit řádků.

MySQL má optimalizace související s LIMIT , ale jde spíše o zastavení prohledávání tabulky, jakmile dosáhne počtu řádků, které se mají vrátit. Optimalizátor může stále v plánu EXPLAIN hlásit, že to možná očekává musíte naskenovat celou tabulku.

Časté nedorozumění ohledně FORCE INDEX je, že si vynucuje použití indexu. :-)Ve skutečnosti, pokud dotaz nemůže použijte index (nebo pokud dostupné indexy nemají pro tento dotaz žádnou výhodu), FORCE INDEX nemá žádný účinek.

K vašemu komentáři:

Stránkování je častým neštěstím webových aplikací založených na datech. Navzdory tomu, jak běžná je tato funkce, není snadné ji optimalizovat. Zde je několik tipů:

  • Proč se ptáte s offsetem 2955900? Opravdu očekáváte, že uživatelé projdou tolik stránek? Většina uživatelů to vzdá po několika stránkách (přesný počet závisí na typu aplikace a datech).

  • Snižte počet dotazů. Vaše funkce stránkování by mohla načíst prvních 5–10 stránek, i když uživateli zobrazí pouze první stránku. Uložte ostatní stránky do mezipaměti s předpokladem, že uživatel postoupí přes několik stránek. Pouze v případě, že postoupí za sadu stránek uloženou v mezipaměti, musí vaše aplikace provést další dotaz. Můžete dokonce uložit všech 10 stránek v Javascriptu do mezipaměti v prohlížeči klienta, takže kliknutí na „Další“ je okamžité pro ně (alespoň pro těch prvních pár stránek).

  • Nedávejte na žádné uživatelské rozhraní tlačítko „Poslední“, protože na něj lidé kliknou ze zvědavosti. Všimněte si, že Google má tlačítko "Další", ale ne tlačítko "Poslední". Samotné uživatelské rozhraní tedy odrazuje lidi od spouštění neefektivních dotazů s vysokými offsety.

  • Pokud uživatel postupuje o jednu stránku vpřed, použijte nejvyšší hodnotu id vrácenou na předchozí stránce v klauzuli WHERE dotazu na další stránku. Tj. následující dělá použijte index i bez nápovědy FORCE INDEX:

    SELECT * FROM thistable WHERE id > 544 LIMIT 20
    



  1. zmatek se sčítáním 2 časových hodnot

  2. Jak analyzovat JSON v postgresql

  3. Vysvětlení velikosti úložiště „datetimeoffset“ na serveru SQL

  4. Přístup odepřen uživateli ''@'localhost' (pomocí hesla:NE)