Je to pomalé, protože potřebuje najít horní offset
řádků a naskenujte dalších 100. Žádná optimalizace to nezmění, když máte co do činění s velkými offsety.
Důvodem je, že váš dotaz doslova instruuje DB engine k návštěvě mnoha řádků pomocí offset 3900000
-- to je 3,9 milionu řádků. Možností, jak to poněkud urychlit, není mnoho.
Pomůže superrychlá RAM, SSD atd. Ale tím získáte pouze konstantní faktor, což znamená, že to bude pouze kopání plechovky, dokud nedosáhnete dostatečně většího offsetu.
Zajištění toho, že se stůl vejde do paměti, se spoustou dalších rezerv také pomůže větším konstantním faktorem - s výjimkou poprvé. To však nemusí být možné s dostatečně velkou tabulkou nebo indexem.
Zajištění, že provádíte skenování pouze s indexem, bude do určité míry fungovat. (Viz odpověď velis; má mnoho předností.) Problém je v tom, že pro všechny praktické účely si můžete index představit jako tabulku ukládající umístění disku a indexovaná pole. (Je to více optimalizované, ale je to rozumná první aproximace.) S dostatečným počtem řádků budete stále narážet na problémy s dostatečně větším offsetem.
Snaha o uložení a udržení přesné polohy řádků je také jistě nákladným přístupem. (To navrhuje např. benjist.) I když je to technicky proveditelné, trpí omezeními podobnými těm, která vyplývají z použití MPTT se stromovou strukturou:výrazně získáte na čtení, ale skončíte s nadměrnou dobou zápisu, když je uzel vložen, aktualizován nebo odstraněn takovým způsobem, že je třeba aktualizovat velké kusy dat.
Jak je doufejme jasnější, neexistuje žádná skutečná kouzla, když se zabýváte tak velkými offsety. Často je lepší podívat se na alternativní přístupy.
Pokud stránkujete na základě ID (nebo pole data nebo jakékoli jiné indexovatelné sady polí), potenciálním trikem (který používá například blogspot) by bylo, aby váš dotaz začínal na libovolném místě v indexu.
Řečeno jinak, místo:
example.com?page_number=[huge]
Udělejte něco jako:
example.com?page_following=[huge]
Tímto způsobem si ve svém indexu udržíte stopu, kde se nacházíte, a dotaz bude velmi rychlý, protože může zamířit přímo do správného výchozího bodu, aniž byste museli procházet gazilión řádků:
select * from foo where ID > [huge] order by ID limit 100
Přirozeně ztrácíte schopnost skočit např. strana 3000. Ale zamyslete se nad tím upřímně:kdy jste naposled skočili na velké číslo stránky na webu, místo abyste si prohlédli jeho měsíční archivy nebo použili jeho vyhledávací pole?
Pokud stránkujete, ale chcete jakýmkoli způsobem ponechat stránku odsazenou, dalším přístupem je zakázat použití většího čísla stránky. Není to hloupé:to je to, co Google dělá s výsledky vyhledávání. Když spustíte vyhledávací dotaz, Google vám poskytne odhadovaný počet výsledků (přiměřený počet můžete získat pomocí explain
), a pak vám umožní procházet prvních několik tisíc výsledků – nic víc. Dělají to mimo jiné z důvodů výkonu – přesně toho, na který narážíte.