I N F O W A R Eobr. 2obr. 3obr. 4 obr. 5úrovni stromovej štruktúry indexu a tou sú samotnédátové stránky (obr. 2).Pre dopyty obsahujúce za klauzulou WHERE rozsahydát sú klastrované indexy <strong>na</strong>jefektívnejšímprístupom k dátam. Èasto sú vytvárané <strong>na</strong>d ståpcamis identifikátorom (spolu s primárnym k¾úèom).Keïe klastrovaný index definuje fyzické poradiedát, môe by <strong>na</strong>d jednou tabu¾kou vytvorenýmaximálne jeden takýto index.Iná situácia je pri neklastrovaných indexoch. Dátovéstránky zostávajú nezmenené. Je to v prípadeHEAP a aj vtedy, ak je vytvorený klastrovaný index.Pri vytvorení indexu sa vytvoria indexové stránky(sú to vlastne dátové stránky, <strong>na</strong> ktorých sa ne<strong>na</strong>chádzajúvšetky údaje z tabu¾ky, ale len dáta obsiahnutév indexovanom poli). Kadý záz<strong>na</strong>m obsahuje<strong>na</strong>vyše aj pointer odkazujúci <strong>na</strong> konkrétny záz<strong>na</strong>mv dátovej stránke (obr. 3). Ak takúto štruktúru vytvoríme<strong>na</strong>d u vytvoreným klastrovaným indexom,spomí<strong>na</strong>ný pointer sa mení <strong>na</strong> dáta ståpca, <strong>na</strong>d ktorýmje klastrovaný index vytvorený. Index môemevytvára aj <strong>na</strong>d dvoma a viacerými po¾ami. V takomtoprípade ide o zloený index. Jeho èastým vyuitímje optimalizácia dopytov. Ak si zvolíme ako èlenovindexu kombináciu polí, ktoré sa <strong>na</strong>chádzajú v príkazeSELECT, za klauzulou JOIN aj WHERE, ohlas <strong>na</strong>dopyt môe by z<strong>na</strong>ène kratší ako pri inom benomdopyte. Polia, ktoré urèíme pre zloený index, bynemali by prive¾ké, aby nedochádzalo k prílišnémuzväèšovaniu dátových súborov. Keby sme teda vytvorilineklastrovaný zloený index, potom by <strong>na</strong>stalstav, keï by sa všetky potrebné dáta <strong>na</strong>chádzali <strong>na</strong>indexových stránkach. SQL potom zniuje poèetvstupných a výstupných operácií (I/O) pri prístupe<strong>na</strong> di<strong>sk</strong>ový subsystém, lebo nie je nútený vyh¾adáva<strong>na</strong> dátových stránkach, ale všetky potrebné dáta máu <strong>na</strong> indexových stránkach.PRÍSTUP K DÁTAMSkúsme si teraz prirov<strong>na</strong> vyh¾adávanie konkrétnychzáz<strong>na</strong>mov v tabu¾ke SQL k vyh¾adávaniu konkrétnehomiesta vo ve¾kom meste. Hneï prvýmspôsobom vyh¾adávania bude blúdenie s mapouv ruke èie vyh¾adávanie bez indexov – heap. Ak siprimyslíme vyh¾adávanie adresy v nejakej priemyselnejštvrti, dojem bude doko<strong>na</strong>lý. V meste existujeve¾a rôznych výkopov, kanálov, ulice bývajú èastodlhé a oz<strong>na</strong>èované len <strong>na</strong> koncoch. Podobne SQLpri vyh¾adávaní jedného záz<strong>na</strong>mu musí prejs všetkydátové stránky. Napríklad chceme vyh¾ada zamest<strong>na</strong>ncas interným èíslom 1587. Kadá jed<strong>na</strong>pouívate¾<strong>sk</strong>á tabu¾ka má záz<strong>na</strong>m v tabu¾ke sysindexesa prvým krokom SQL bude vyh¾adanie jejzáz<strong>na</strong>mu. Zistí, e záz<strong>na</strong>m obsahuje v poli indidhodnotu 0. Na základe tejto informácie si pozrieúdaj v ståpci FirstIAM, ktorý povie SQL, kde sa <strong>na</strong>chádzaprvá stránka mapy alokácie indexu (FirstIndex Allocation Map). Táto mapa je jediným spájajúcimèlánkom stránok vytvárajúcich tabu¾kuv heape.Rozviòme ïalej náš príklad blúdiaceho turistu:okrem mapy bude ma aj presnú adresu h¾adanéhomiesta. Na obr. 4 je zobrazený postup pri prístupek dátam. Tak ako pri vyh¾adávaní adresy pomocoumapy aj SQL Server musí <strong>sk</strong>enova kadý jedenextent, aby zistil èo len jeden záz<strong>na</strong>m. Tento prístupk dátam je <strong>na</strong>jpomalší a <strong>na</strong>zýva sa table scan.Grafické znázornenie tohto prístupu po<strong>sk</strong>ytuje nástrojQuery A<strong>na</strong>lyzer. Exekuèný plán zobrazímepomocou klávesovej <strong>sk</strong>ratky Ctrl + K a vyko<strong>na</strong>nia<strong>na</strong>sledujúceho príkazu:USE NorthwindSELECT * FROM dbo.territoriesNa karte Execution Plan sa zobrazí grafické znázornenievyko<strong>na</strong>nia dopytu a dodatoèné informácie(ak kurzorom myši vyberiete ikonu tabu¾kového<strong>sk</strong>enu). Tabu¾kové <strong>sk</strong>eny sú rýchlejšie ako preh¾adávanieindexovaných stránok iba v prípade malýchtabuliek.Ïalší príklad je klastrovaný index a môeme hoprirov<strong>na</strong> k vyh¾adávaniu pomocou Global PositioningSystem (GPS). Podobne ako v aute, keï dostávavodiè inštrukcie typu „zaboè do¾ava a po desiatichminútach doprava“, zí<strong>sk</strong>ava informácie o vyh¾adávanomzáz<strong>na</strong>me aj SQL Server. Má ich však z indexovýchstránok, a nie zo satelitu. Na indexovýchstránkach sú uloené hodnoty indexovaného ståpca,ktoré slúia ako porovnávacie hodnoty. Ak sa<strong>na</strong>príklad vyh¾adáva záz<strong>na</strong>m zamest<strong>na</strong>nca s internýmèíslom 1587, SQL postupuje takto: Najprv<strong>sk</strong>ontroluje sysindexes tabu¾ku a zistí, e tam je záz<strong>na</strong>mv ståpci indid 1. To z<strong>na</strong>mená klastrovaný2/<strong>2004</strong> PC REVUE 129
I N F O W A R Eindex. Potom kontroluje záz<strong>na</strong>m v ståpci root, ktorýje definovaný dátovým typom binárnym a obsahujeúdaj o umiestnení koreòovej stránky klastrovanéhoindexu. Ak ju lokalizuje, zaène porovnávah¾adanú hodnotu, v <strong>na</strong>šom prípade je to èíslo 1587.SQL ju h¾adá <strong>na</strong>jprv <strong>na</strong> koreòovej stránke, ak tamnie je, postupuje o úroveò nišie, a to <strong>na</strong> základeprepojenia indexových stránok. Tentoraz nemusíís pri lokalizácii nového extentu alebo stránky <strong>na</strong>FirstIAM (pozera do mapy), ale ide priamo a <strong>na</strong>h¾adaný údaj. Pri takomto <strong>sk</strong>ene je niší poèet <strong>sk</strong>enovanýchstránok a tým aj operácií I/O <strong>na</strong> di<strong>sk</strong>ovomsubsystéme. Ilustráciou je obrázok è. 5 a takistoaj exekuèný plán, ktorý sa zobrazí v aplikáciiQuery A<strong>na</strong>lyzer po príkaze:USE NorthwindSELECT * FROM dbo.[Order Details]Pomocou príkazu SET STATISTICS IO ON môemezisti poèet <strong>sk</strong>enovaných dátových stránok. Pri absenciiindexu sa ich poèet výrazne zvýši. Klastrovanýindex by sa dal prirov<strong>na</strong> aj k slovníku. Tak akosú v slovníku objekty (slová) zoraïované pod¾aabecedy, aj riadky v tabu¾ke <strong>na</strong> SQL Serveri sú zoraïovanépod¾a po-¾a, <strong>na</strong>d ktorým je indexvytvorený. H¾adaniev slovníku jetriviálne. Ak h¾adámeslovo cluster, ve¾mirýchlo vyberiemestranu, kde saslovo <strong>na</strong>chádza, a<strong>na</strong> tejto strane hovyh¾adáme – „pre<strong>sk</strong>enujeme“ju. Kebyvšak klastrovanýindex chýbal, boloby takmer nemonévyh¾ada všetky vý<strong>sk</strong>ytyslova cluster.K tejto asociácii saešte vrátime prineklastrovanom obr. 6indexe.Vráme sa k a<strong>na</strong>lógii vyh¾adávania konkrétnehomiesta v neznámom meste. Tu je <strong>na</strong>jpriliehavejšieprirov<strong>na</strong>nie k <strong>sk</strong>úsenému turistovi s mapou. Kým prištruktúre HEAP musel blúdiaci neustále <strong>na</strong>zera domapy a blúdi po uliciach, v neklastrovanom indexesa turistovi staèí raz pozrie do mapy a <strong>na</strong> prvýkrátnájde miesto urèenia. Ak teda h¾adáme záz<strong>na</strong>mzamest<strong>na</strong>nca 1587, SQL <strong>na</strong>jprv kontroluje sysindexes,kde zistí hodnotu väèšiu ako 1. Na základe údajav poli root vyh¾adá koreò neklastrovaného indexua zaène preh¾adáva indexové stránky a hodnoty <strong>na</strong>nich porovnáva s èíslom 1587. Po tom, èo príde <strong>na</strong>listovú úroveò indexových stránok, nájde pri hodnote1587 pointer. Ten ho odkazuje <strong>na</strong> konkrétnyextent, konkrétny súbor a definuje aj konkrétnyzáz<strong>na</strong>m. Vyh¾adanie je teda jednoduché aj vtedy, aksamotné dátové stránky nie sú usporiadané (neklastrovanýindex <strong>na</strong> heape). Keby bol v tejto tabu¾kevytvorený aj klastrovaný index (<strong>na</strong>pr. <strong>na</strong>d po¾omPriezvi<strong>sk</strong>o), <strong>na</strong>miesto èíselného pointera by sa tu <strong>na</strong>chádzalúdaj (èie priezvi<strong>sk</strong>o zamest<strong>na</strong>nca è. 1587).Problém by vznikol vtedy, keby výsledok dopytupozostával z viacerých záz<strong>na</strong>mov. H¾adajme zamest<strong>na</strong>ncovod èísla 25 po 1587. Turista by musel pozerado mapy vdy práve raz pre kadé h¾adané miesto.SQL server sa teda musí pre kadý záz<strong>na</strong>m vráti<strong>na</strong> indexové stránky neklastrovaného indexu. Prerozsahy dát teda tento spôsob indexovania nie jeefektívny (obr. 6).INDEXOVANÉ POH¼ADYAby boli indexy úèinné, musia by dobre <strong>na</strong>vrhnuté.Výz<strong>na</strong>mným pomocníkom je sprievodca IndexTuning Wizard. Pomocou tohto sprievodcu dokáe<strong>sk</strong>úsený databázový administrátor definova optimálnuštruktúru indexov <strong>na</strong>d tabu¾kami. Dobre<strong>na</strong>vrhnuté indexy vytvoria predpoklady <strong>na</strong> maximálnyvýkon servera nielen pri èítaní, ale aj pri zápisedát. Niekedy však databázové aplikácie vykonávajúdopytovanie poh¾adov, ktoré sú vytvorené <strong>na</strong>dtabu¾kami. Poh¾ady však nie sú fyzické dáta a ne<strong>na</strong>chádzajúsa <strong>na</strong> dátových ani indexových stránkach.Jediné, èo je uloené <strong>na</strong> databázovom serveri, jedefinícia poh¾adu. SQL teda vdy pri vykonávanídopytu <strong>na</strong>d poh¾adom kontroluje jeho definíciu apotom vykoná dopyt <strong>na</strong>d podliehajúcimi tabu¾kami.Aj v tomto prípade SQL vyuíva indexovú štruktúru.Poh¾ady sú „virtuálne dáta“, t. j. okrem vlastnýchdát obsahujú aj vypoèítané ståpce alebo sú spojeniamiviacerých tabuliek (klauzulou JOIN). Dopyty <strong>na</strong>dnimi sa budú pouívate¾om zda relatívne pomalé.Microsoft SQL Server od verzie 2000, ale len v edíciiENTERPRISE ponúka monos indexova aj poh¾ady.Základný zmysel indexovania poh¾adov je v urýchlenídopytovania cez poh¾ady a <strong>na</strong>vyše dáva SQLServeru monos vyuíva vypoèítané dáta, ktoré sauloia <strong>na</strong> indexové stránky. Ak je <strong>na</strong>príklad pri dopytenevyhnutné vráti pouívate¾ovi vypoèítané ståpcedát, SQL musí pri kadom (!) takomto úkone dátareálne vypoèítava. Keby sme však mali indexovanýpoh¾ad, ktorý takéto dáta obsahuje, SQL si ich jednoducho„stiahne“ z indexových stránok. Dá sa tedapoveda, e za urèitých okolností indexovaniepoh¾adov z<strong>na</strong>ène zvyšuje výkon databázového servera.Všimnime si podmienky, ktoré treba dodra privytváraní indexu <strong>na</strong>d poh¾admi. Je potrebné dodra<strong>na</strong>stavenia spojenia (session settings) pri vytváranípoh¾adu, pri vykonávaní príkazov INSERT,UPDATE a DELETE a pri samotnom pouívaní poh¾aduQuery Optimizer komponentom.Okrem toho musí poh¾ad spåòa <strong>na</strong>sledujúce podmienky: parameter WITH SCHEMABINDING je povinný referencia je povolená len k tabu¾kám tej istejdatabázy klauzula GROUP BY nesmie obsahova HAVING,CUBE alebo ROLLUP klauzula OUTER JOIN je zakázaná klauzula UNION je zakázaná klauzula DISTINCT alebo TOP je zakázaná funkcia ROWSET (<strong>na</strong>pr. OPENROWSET) je zakázaná delené tabu¾ky alebo poddopyty sú zakázané ANSI_NULLS a QUOTED_IDENTIFIER sú pri vytváranív polohe ONNastavenia spojenia Musí by Východi<strong>sk</strong>ováhodnotaANSI_NULLS ON OFFANSI_PADDING ON ONANSI_WARNING ON OFFARITHABORT ON OFFCONCAT_NULL_YEILDS_NULL ON OFFNUMERIC_ROUNDABORT OFF OFFQUOTED_IDENTIFIER ON OFFVýhody pouitia indexovaných poh¾adov simôeme ilustrova <strong>na</strong> dopyte, ktorý bude zí<strong>sk</strong>avainformácie o poète dodávate¾ov v databázeNorthwind.USE NorthwindSELECT s.CompanyName,COUNT_BIG(*) AS COUNTFROM Orders o INNER JOIN Shippers sON o.ShipVia=s.ShipperIDGROUP BY CompanyNamePomocou príkazu SET SHOWPLAN_ALL ON mô-eme ilustrova, ako dopyt pristupuje k dátam.Rozdiel bude zjavný, ak si vytvoríme poh¾ad a ten„oindexujeme“. Index vytvorený <strong>na</strong>d týmto poh¾adomsa bude vyuíva tak pri uvedenom dopyte,ako aj pri dopytovaní poh¾adu.Na záver uveïme <strong>sk</strong>ript potrebný <strong>na</strong> vytvoreniespomí<strong>na</strong>ného poh¾adu:SET QUOTED_IDENTIFIER ONGOCREATE VIEW ShipVwWITH SCHEMABINDINGASSELECT s.CompanyName,COUNT_BIG(*) AS COUNTFROM dbo.Orders o INNER JOIN dbo.Shippers sON o.ShipVia=s.ShipperIDGROUP BY CompanyNameNad týmto poh¾adom potom mono vytvára klastrovanýindex:CREATE UNIQUE CLUSTERED INDEX sch_idx_vwON ShipVw(CompanyName)Peter Gallo130 PC REVUE 2/<strong>2004</strong>