Proč mám hinty v Oracle rád a proč je nenávidím

Na rozdíl od předchozích čistě technických článků si tentokrát dovolím krátké zamyšlení nad hinty v Oracle, ke kterým mám poněkud nejednoznačný vztah. Občas sice ve slabší chvilce připustím že se hodí, ale většinou je celkem upřímně nenávidím ...

Předem bych rád upozornil že tento článek prezentuje moje osobní názory na hinty, které ale samozřejmě nelze nijak exaktně dokázat. Snažil jsem se samozřejmě uvést pádné argumenty pro svůj postoj, ale i přes to se jedná o osobní názor se kterým nemusíte souhlasit.

Kladná stránka hintů

Nejdříve se podívejme na kladnou stránky hintů. Zaprvé lze jejich prostřednictvím databázi poskytnout doplňující informace, které umožní vybrání lepšího execution planu. Hinty dokumentované v Oracle lze rozdělit zhruba do následujících skupin:

  • hinty určující optimalizační kritérium, tj. zda je žádoucí co nejvyšší celková propustnost (ALL_ROWS) nebo pro co nejrychlejší dodání prvních řádků (FIRST_ROWS)
  • hinty předepisující způsob přistupu k dané tabulce, tj. zda má být sekvenčně čtena celá tabulka (FULL) nebo zda a jakým způsobem má být využit index (INDEX, NO_INDEX, INDEX_ASC, INDEX_DESC, INDEX_FFS, ...)
  • hinty předepisující pořadí (LEADING, ORDERED) a způsob slučování tabulek (USE_NL, USE_MERGE, USE_HASH, ...)
  • hinty určující paralelní zpracování dotazů (PARALLEL, PARALLEL_INDEX, ...)

Všechny tyto hinty vám umožňují "podstrčit" databázi zajímavé dodatečné informace o tom k čemu dotaz bude sloužit, jakým způsobem ho lze paralelizovat a podobně. Důležité je pochopení že databáze během vytváření query planu pracuje pouze s odhady statistik, a že nemusí vždy dojít ke skutečně optimálnímu plánu - v případě zastaralých statistik nebo nedostatečně podrobných statistik dokonce může dojít k velmi špatnému query plánu. A právě hinty jsou jednou z možnosti jak databázi "umravnit" a naznačit jí správnou cestu.

Jistě - můžete namítnout že databáze by si měla sesbítat všechny potřebné statistiky (ostatně kdo jiný by to měl dělat, že), a na základě nich se optimálně rozhodnout, ale v praxi to samozřejmě bývá trochu jinak. Zaprvé prostě není technicky možné sbírat všechny možné statistiky (o tabulkách,  všech kombinacích sloupců, atd.) protože by to vyžadovalo příliš mnoho výkonu.

Navíc některé informace databáze jednoduše nemá protože se týkají "okolního světa" a databáze je tak musí odhadovat, nebo se spoléhat na odhady administrátorů - typickým příkladem jsou parametry týkající se hardware a operačního systému. Např. stanovení "ceny" náhodného a sekvenčního čtení z disku může být celkem oříšek, protože co systém to mírně jiné charakteristiky. Existuje několik variant disků (EIDE, SATA, SAS, SCSI, FC, SSD, ...) s různými otáčkami (5400 až 15000 za minutu), různé úrovně RAID polí (0, 1, 10, 01, 5, ...), hardwarová a softwarová RAID řešení, různí výrobci diskových řadičů z nichž každý má má několik produktových řad, jednotlivé řadiče mají cache o různé velikosti, ... Prostě i když se základní vlastnosti dají odhadnout, jsou to stále jenom odhady.

Pokud se administrátor nebo databáze při jejich nastavení zmýlí hodně, většinou si toho velmi záhy všimnete, protože se databáze bude doslova plazit. Pokud se ale zmýlí "jenom trochu" může to být paradoxně horší, protože databáze ve většině případů bude fungovat správně. Totiž pokud jsou rozdíly mezi skutečnými cenami execution planů dostatečně velké, nebo pokud jsou execution plany vyrovnané, potom ani drobné nepřesnosti v odhadech nezpůsobí chybný výběr velmi špatného execution planu.

V některých případech (zejména v případě složitých dotazů kde se nepřesnosti mohou dostatečně nakumulovat) ale dojde k výběru špatného execution planu, a dotaz pak poběží rychlostí chromého šneka. V takovém případě buď můžete administrátora přemlouvat aby upravil nastavení databáze (do čehož se mu na produkčním serveru asi moc chtít nebude, zejména pokud tam běží víc aplikací a nikdo další si nestěžuje), nebo pomocí hintu databázi "pošťouchnete" správným směrem.

Čímž se dostáváme k druhému využití hintů - je nepopiratelné že každý dostatečně složitý software obsahuje chyby, nedomyšlenosti, případně se v některých situacích chová neočekávaně, a ani Oracle samozřejmě není výjimkou. A právě hinty jsou jednou z možností jak tyto problémy obejít. Příkladem takového neočekávaného chování může být například tento SQL puzzler a jeho řešení pomocí materialize hintu.

Záporná stránka hintů

Hinty ale bohužel mají i své stinné stránky - rád bych jmenoval alespoň dvě následující.

Prvním problémem je že hinty do kódu aplikace (jehož jsou SQL dotazy součástí) vlastně zanášejí informace o datech a jejich statistických vlastnostech, či spíše vývojářovu představu o nich. Problém je že vývojář vychází z informací které má v době vývoje (například předpokládá že tabulka je malá a vždy malá i zůstane), což se ale během životnosti aplikace často změní (malá tabulka neočekávaně rychle naroste). Informace zakódované do SQL dotazů ve formě hintů ale tyto dynamické změny pochopitelně nemohou reflektovat, což může působit značné problémy (většinou s výkonem).

Tento problém se týká zejména hintů přímo ovlivňujících způsob přístupu k tabulkám, pořadí a způsob joinování tabulek apod. Do jisté míry se ale týká také hintů určujících optimalizační kritéria (ALL_ROWS a FIRST_ROWS) - totiž pokud dotaz například zapouzdřím do metody v DAO objektu, co zabrání dalším vývojářům používat ho v situaci neodpovídající zvolenému optimalizačnímu kritériu?

Druhým výrazným problémem je že hinty z pohledu vývoje mohou představovat jakousi "brzdu pokroku," ať již na straně aplikace nebo databáze. Co tím mám na mysli?

Řekněme že vyvíjíte aplikaci která přistupuje k databázi, a zjistíte že část aplikace je špatně navržena (například byl zvolen špatný způsob dekompozice) což působí závažné výkonnostní problémy. Z dlouhodobého hlediska by správným řešením jednoznačně byl refactoring, ale řekněme že kolega vývojář zjistí že jako dočasné řešení lze použít právě hinty. Není to ideální, ale jako dočasné řešení to víceméně funguje. Dostanete se ale k tomu plánovanému refactoringu? Nejspíše ne, protože ono to konec konců jakž takž funguje, a vždycky se najde něco důležitějšího.

Obdobně to funguje na straně databáze - skutečných chyb se to asi netýká, ale v případě některých nedomyšleností resp. neočekávaných side-effectů se úvahy ubírají zhruba stejnou cesto jako v případě aplikace. Máme problém? Máme. Máme nějaký vhodný workaround? Máme - hint. Budeme to dál řešit? Nebudeme ...

Odkazy

 

Komentáře

K tomuto článku zatím žádné komentáře neexistují (nebo čekají na schválení).

Nový komentář

Všechny komentáře podléhají schválení - mezi odesláním komentáře a jeho zobrazením na této stránce tedy může být prodleva. Vyplníte-li e-mailovou adresu, budete o schválení či neschválení komentáře informováni.

V titulku ani v textu nejsou povoleny HTML tagy - budou automaticky odstraněny. Odstavec ukončíte prázdným řádkem.

(nepovinné)