V predošlom článok Popísal som koncepciu a implementáciu databázy postavenej na základe funkcií, nie tabuliek a polí ako v relačných databázach. Poskytol mnoho príkladov ukazujúcich výhody tohto prístupu oproti klasickému. Mnohí ich považovali za nedostatočne presvedčivé.
V tomto článku ukážem, ako vám tento koncept umožňuje rýchlo a pohodlne vyvažovať zápisy a čítania do databázy bez akejkoľvek zmeny v prevádzkovej logike. Podobnú funkcionalitu sa pokúšali implementovať v moderných komerčných DBMS (najmä Oracle a Microsoft SQL Server). Na konci článku ukážem, že to, čo urobili, mierne povedané, veľmi nevyšlo.
Popis
Ako predtým, pre lepšie pochopenie začnem popis príkladmi. Povedzme, že potrebujeme implementovať logiku, ktorá vráti zoznam oddelení s počtom zamestnancov v nich a ich celkovou mzdou.
Vo funkčnej databáze by to vyzeralo takto:
CLASS Department ‘Отдел’;
name ‘Наименование’ = DATA STRING[100] (Department);
CLASS Employee ‘Сотрудник’;
department ‘Отдел’ = DATA Department (Employee);
salary ‘Зарплата’ = DATA NUMERIC[10,2] (Employee);
countEmployees ‘Кол-во сотрудников’ (Department d) =
GROUP SUM 1 IF department(Employee e) = d;
salarySum ‘Суммарная зарплата’ (Department d) =
GROUP SUM salary(Employee e) IF department(e) = d;
Zložitosť vykonania tohto dotazu v akomkoľvek DBMS bude ekvivalentná O (počet zamestnancov)pretože tento výpočet vyžaduje naskenovať celú tabuľku zamestnancov a následne ich zoskupiť podľa oddelení. V závislosti od zvoleného plánu bude existovať aj nejaký malý (domnievame sa, že zamestnancov je oveľa viac ako oddelení). O (zaznamenaný počet zamestnancov) alebo O (počet oddelení) na zoskupovanie a pod.
Je jasné, že réžia vykonávania môže byť v rôznych DBMS odlišná, ale zložitosť sa nijako nezmení.
V navrhovanej implementácii funkčný DBMS vygeneruje jeden poddotaz, ktorý vypočíta požadované hodnoty pre oddelenie a potom vytvorí JOIN s tabuľkou oddelení, aby získal názov. Pre každú funkciu je však pri deklarácii možné nastaviť špeciálny fix MATERIALIZED. Systém automaticky vytvorí zodpovedajúce pole pre každú takúto funkciu. Pri zmene hodnoty funkcie sa v tej istej transakcii zmení aj hodnota poľa. Pri prístupe k tejto funkcii sa sprístupní vopred vypočítané pole.
Najmä ak nastavíte funkcie MATERIALIZED countEmployees и mzdaSum, následne do tabuľky so zoznamom oddelení pribudnú dve polia, v ktorých bude uložený počet zamestnancov a ich celková mzda. Vždy, keď dôjde k zmene zamestnancov, ich platov alebo príslušnosti k oddeleniam, systém automaticky zmení hodnoty týchto polí. Vyššie uvedený dotaz bude pristupovať priamo k týmto poliam a bude vykonaný v O (počet oddelení).
Aké sú obmedzenia? Len jedna vec: takáto funkcia musí mať konečný počet vstupných hodnôt, pre ktoré je definovaná jej hodnota. V opačnom prípade nebude možné zostaviť tabuľku, ktorá uchová všetky jej hodnoty, pretože nemôže existovať tabuľka s nekonečným počtom riadkov.
Príklad:
employeesCount ‘Количество сотрудников с зарплатой > N’ (Department d, NUMERIC[10,2] N) =
GROUP SUM salary(Employee e) IF department(e) = d AND salary(e) > N;
Táto funkcia je definovaná pre nekonečný počet hodnôt N (vhodná je napríklad akákoľvek záporná hodnota). Preto naň nemôžete dať MATERIALIZED. Ide teda o logické obmedzenie, nie technické (teda nie preto, že by sme ho nevedeli implementovať). V opačnom prípade neexistujú žiadne obmedzenia. Môžete použiť zoskupenia, triedenie, AND a OR, PARTITION, rekurziu atď.
Napríklad v probléme 2.2 predchádzajúceho článku môžete použiť MATERIALIZED na obe funkcie:
bought 'Купил' (Customer c, Product p, INTEGER y) =
GROUP SUM sum(Detail d) IF
customer(order(d)) = c AND
product(d) = p AND
extractYear(date(order(d))) = y MATERIALIZED;
rating 'Рейтинг' (Customer c, Product p, INTEGER y) =
PARTITION SUM 1 ORDER DESC bought(c, p, y), p BY c, y MATERIALIZED;
SELECT contactName(Customer c), name(Product p) WHERE rating(c, p, 1997) < 3;
Systém sám vytvorí jednu tabuľku s typovými kľúčmi Zákazník, Produkt и INTEGER, pridá doň dve polia a aktualizuje hodnoty polí v nich so všetkými zmenami. Keď sa uskutočnia ďalšie volania týchto funkcií, nebudú sa vypočítavať, ale hodnoty sa načítajú z príslušných polí.
Pomocou tohto mechanizmu sa môžete napríklad zbaviť rekurzie (CTE) v dotazoch. Zvážte najmä skupiny, ktoré tvoria strom pomocou vzťahu dieťa/rodič (každá skupina má prepojenie na svojho rodiča):
parent = DATA Group (Group);
Vo funkčnej databáze môže byť rekurzná logika špecifikovaná takto:
level (Group child, Group parent) = RECURSION 1l IF child IS Group AND parent == child
STEP 2l IF parent == parent($parent);
isParent (Group child, Group parent) = TRUE IF level(child, parent) MATERIALIZED;
Keďže pre funkciu je rodič je označený MATERIALIZOVANÝ, potom sa k nemu vytvorí tabuľka s dvoma kľúčmi (skupinami), v ktorej pole je rodič bude pravdivé iba vtedy, ak je prvý kľúč potomkom druhého. Počet záznamov v tejto tabuľke sa bude rovnať počtu skupín vynásobenému priemernou hĺbkou stromu. Ak potrebujete napríklad spočítať počet potomkov určitej skupiny, môžete použiť túto funkciu:
childrenCount (Group g) = GROUP SUM 1 IF isParent(Group child, g);
V dotaze SQL nebude CTE. Namiesto toho bude jednoduchý GROUP BY.
Pomocou tohto mechanizmu môžete tiež ľahko denormalizovať databázu, ak je to potrebné:
CLASS Order 'Заказ';
date 'Дата' = DATA DATE (Order);
CLASS OrderDetail 'Строка заказа';
order 'Заказ' = DATA Order (OrderDetail);
date 'Дата' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;
Pri volaní funkcie dáta pre riadok objednávky sa pole, pre ktoré existuje index, načíta z tabuľky s riadkami objednávky. Keď sa dátum objednávky zmení, systém sám automaticky prepočíta denormalizovaný dátum v riadku.
Výhody
Načo je celý tento mechanizmus? V klasických DBMS, bez prepisovania dotazov, môže vývojár alebo DBA meniť iba indexy, určovať štatistiky a povedať plánovačovi dotazov, ako ich vykonať (a HINTy sú dostupné len v komerčných DBMS). Bez ohľadu na to, ako veľmi sa snažia, nebudú môcť dokončiť prvý dotaz v článku v O (počet oddelení) bez zmeny dopytov alebo pridávania spúšťačov. V navrhovanej schéme vo fáze vývoja nemusíte premýšľať o štruktúre ukladania údajov a o tom, ktoré agregácie použiť. To všetko sa dá jednoducho meniť za behu, priamo v prevádzke.
V praxi to vyzerá takto. Niektorí ľudia rozvíjajú logiku priamo na základe danej úlohy. Nerozumejú algoritmom a ich zložitosti, ani realizačným plánom, ani typom spojení, ani iným technickým komponentom. Títo ľudia sú viac obchodnými analytikmi ako vývojármi. Potom to všetko ide do testovania alebo prevádzky. Umožňuje zaznamenávanie dlhotrvajúcich dopytov. Keď sa zistí dlhý dopyt, iní ľudia (technickejší - v podstate DBA) sa rozhodnú povoliť MATERIALIZED na nejakej medziľahlej funkcii. To trochu spomalí nahrávanie (keďže vyžaduje aktualizáciu dodatočného poľa v transakcii). Výrazne sa však zrýchľuje nielen tento dopyt, ale aj všetky ostatné, ktoré túto funkciu využívajú. Rozhodnúť sa, ktorú funkciu zhmotniť, je zároveň pomerne jednoduché. Dva hlavné parametre: počet možných vstupných hodnôt (to znamená, koľko záznamov bude v príslušnej tabuľke) a ako často sa používa v iných funkciách.
analógy
Moderné komerčné DBMS majú podobné mechanizmy: MATERIALIZOVANÉ ZOBRAZENIE s FAST REFRESH (Oracle) a INDEXEDNÉ ZOBRAZENIE (Microsoft SQL Server). V PostgreSQL nie je možné MATERIALIZED VIEW aktualizovať v transakcii, ale iba na požiadanie (a aj to s veľmi prísnymi obmedzeniami), takže to neuvažujeme. Ale majú niekoľko problémov, ktoré výrazne obmedzujú ich použitie.
Po prvé, materializáciu môžete povoliť iba vtedy, ak ste už vytvorili bežný VIEW. V opačnom prípade budete musieť prepísať zostávajúce požiadavky na prístup k novovytvorenému pohľadu, aby ste mohli použiť túto materializáciu. Alebo nechajte všetko tak, ale bude to prinajmenšom neúčinné, ak existujú určité už vopred vypočítané údaje, ale mnohé dopyty ich nie vždy používajú, ale prepočítavajú.
Po druhé, majú obrovské množstvo obmedzení:
veštec
5.3.8.4 Všeobecné obmedzenia rýchleho obnovenia
Definujúci dotaz materializovaného zobrazenia je obmedzený takto:
Zhmotnený pohľad nesmie obsahovať odkazy na neopakujúce sa výrazy ako napr SYSDATE a ROWNUM.
Zhmotnený pohľad nesmie obsahovať odkazy na RAW or LONGRAW dátové typy.
Nemôže obsahovať a SELECT vypísať poddotaz.
Nemôže obsahovať analytické funkcie (napr. RANK) v SELECT klauzula.
Nemôže odkazovať na tabuľku, na ktorej je an XMLIndex index je definovaný.
Nemôže obsahovať a MODEL klauzula.
Nemôže obsahovať a HAVING klauzula s poddotazom.
Nemôže obsahovať vnorené dopyty, ktoré majú ANY, ALL, Alebo NOTEXISTS.
Nemôže obsahovať a [START WITH …] CONNECT BY klauzula.
Nemôže obsahovať viacero podrobných tabuliek na rôznych miestach.
ONCOMMIT materializované zobrazenia nemôžu mať vzdialené tabuľky podrobností.
Vnorené materializované zobrazenia musia mať spojenie alebo súhrn.
Zhmotnené zobrazenia spojenia a zhmotnené súhrnné zobrazenia s a GROUPBY klauzula nemôže vyberať z tabuľky usporiadanej podľa indexu.
5.3.8.5 Obmedzenia rýchleho obnovenia zhmotnených zobrazení iba s pripojením
Definovanie dotazov pre materializované zobrazenia iba so spojeniami a bez agregátov má nasledujúce obmedzenia rýchleho obnovenia:
Rad všetkých stolov v FROM zoznam sa musí objaviť v SELECT zoznam dopytu.
Protokoly materializovaných zobrazení musia existovať s riadkami pre všetky základné tabuľky v FROM zoznam dopytu.
Nemôžete vytvoriť rýchlo obnoviteľný materializovaný pohľad z viacerých tabuliek s jednoduchými spojeniami, ktoré obsahujú stĺpec typu objektu v SELECT vyhlásenia.
Spôsob obnovenia, ktorý zvolíte, nebude optimálne účinný, ak:
Definujúci dotaz používa vonkajšie spojenie, ktoré sa správa ako vnútorné spojenie. Ak definujúci dotaz obsahuje takéto spojenie, zvážte prepísanie definujúceho dotazu tak, aby obsahoval vnútorné spojenie.
SELECT zoznam materializovaného zobrazenia obsahuje výrazy v stĺpcoch z viacerých tabuliek.
5.3.8.6 Obmedzenia rýchleho obnovenia materializovaných zobrazení s agregátmi
Definovanie dotazov pre materializované zobrazenia pomocou agregátov alebo spojení má nasledujúce obmedzenia rýchleho obnovenia:
Rýchle obnovenie je podporované pre obe ONCOMMIT a ONDEMAND zhmotnené názory, platia však tieto obmedzenia:
Všetky tabuľky v materializovanom zobrazení musia mať denníky materializovaných zobrazení a denníky materializovaných zobrazení musia:
Obsahuje všetky stĺpce z tabuľky, na ktorú odkazuje materializované zobrazenie.
Špecifikujte pomocou ROWID a INCLUDINGNEWVALUES.
Určite SEQUENCE klauzulu, ak sa očakáva, že tabuľka bude obsahovať kombináciu vložení/priameho načítania, odstránenia a aktualizácií.
Iba SUM, COUNT, AVG, STDDEV, VARIANCE, MIN a MAX sú podporované pre rýchle obnovenie.
COUNT(*) musí byť špecifikované.
Agregátne funkcie sa musia vyskytovať len ako vonkajšia časť výrazu. Teda agregáty ako napr AVG(AVG(x)) or AVG(x)+ AVG(x) nie sú dovolené.
Pre každý agregát ako napr AVG(expr), zodpovedajúce COUNT(expr) musí byť prítomný. Oracle to odporúča SUM(expr) byť špecifikovaný.
If VARIANCE(expr) or STDDEV(expr) je špecifikovaný, COUNT(expr) a SUM(expr) musí byť špecifikované. Oracle to odporúča SUM(expr *expr) byť špecifikovaný.
SELECT stĺpec v definujúcom dotaze nemôže byť zložitý výraz so stĺpcami z viacerých základných tabuliek. Možným riešením tohto problému je použitie vnoreného materializovaného zobrazenia.
SELECT zoznam musí obsahovať všetky GROUPBY stĺpy.
Materializovaný pohľad nie je založený na jednej alebo viacerých vzdialených tabuľkách.
Ak použijete a CHAR typu údajov v stĺpcoch filtra protokolu materializovaného zobrazenia, znakové sady hlavnej lokality a materializovaného zobrazenia musia byť rovnaké.
Ak má materializovaný pohľad jednu z nasledujúcich možností, rýchle obnovenie je podporované iba na konvenčných vložkách DML a priamom načítaní.
Zhmotnené pohľady s MIN or MAX agregáty
Zhmotnené pohľady, ktoré majú SUM(expr) ale nie COUNT(expr)
Zhmotnené pohľady bez COUNT(*)
Takýto zhmotnený pohľad sa nazýva len vložkový zhmotnený pohľad.
Zhmotnený pohľad s MAX or MIN je rýchlo obnoviteľný po vymazaní alebo zmiešaných príkazoch DML, ak nemá a WHERE klauzula.
Rýchle obnovenie max/min po odstránení alebo zmiešanom DML nemá rovnaké správanie ako v prípade iba vloženia. Vymaže a prepočíta maximálne/min hodnoty pre dotknuté skupiny. Musíte si uvedomiť jeho vplyv na výkon.
Materializované zobrazenia s pomenovanými zobrazeniami alebo poddotazmi v FROM klauzulu možno rýchlo obnoviť za predpokladu, že pohľady možno úplne zlúčiť. Informácie o tom, ktoré zobrazenia sa zlúčia, nájdete v časti Referenčný jazyk SQL databázy Oracle.
Ak neexistujú žiadne vonkajšie spojenia, môžete mať ľubovoľné výbery a spojenia WHERE klauzula.
Zhmotnené agregované pohľady s vonkajšími spojmi sa dajú rýchlo obnoviť po konvenčnom DML a priamom zaťažení za predpokladu, že bola upravená iba vonkajšia tabuľka. Tiež musia existovať jedinečné obmedzenia pre stĺpce spojenia vnútornej tabuľky spojení. Ak existujú vonkajšie spojenia, všetky spojenia musia byť spojené pomocou ANDs a musia použiť rovnosť (=) operátor.
Pre zhmotnené pohľady s CUBE, ROLLUP, zoskupovanie množín alebo ich zreťazenie, platia nasledujúce obmedzenia:
SELECT zoznam by mal obsahovať rozlišovač zoskupení, ktorý môže byť a GROUPING_ID fungovať na všetkých GROUPBY výrazy resp GROUPING funguje jedna pre každého GROUPBY výraz. Napríklad, ak GROUPBY klauzula materializovaného pohľadu je „GROUPBYCUBE(a, b)", potom SELECT zoznam by mal obsahovať buď "GROUPING_ID(a, b)» alebo «GROUPING(a)ANDGROUPING(b)» aby bol zhmotnený pohľad rýchlo obnoviteľný.
GROUPBY by nemalo viesť k žiadnym duplicitným zoskupeniam. Napríklad, "GROUP BY a, ROLLUP(a, b)"nie je rýchlo obnoviteľné, pretože vedie k duplicitným zoskupeniam"(a), (a, b), AND (a)".
5.3.8.7 Obmedzenia rýchleho obnovenia materializovaných zobrazení s UNION ALL
Zhmotnené pohľady s UNIONALL nastaviť podporu operátora REFRESHFAST možnosť, ak sú splnené tieto podmienky:
Definujúci dotaz musí mať UNIONALL operátora na najvyššej úrovni.
UNIONALL Operátor nemôže byť vložený do poddotazu, s jednou výnimkou: The UNIONALL môže byť v poddotaze v FROM za predpokladu, že definujúci dotaz má formu SELECT * FROM (zobraziť alebo poddotaz s UNIONALL) ako v nasledujúcom príklade:
CREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM customers c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM customers c WHERE c.cust_last 'Jones'); VYTVORIŤ MATERIALIZOVANÉ ZOBRAZENIE unionall_inside_view_mv RÝCHLE OBNOVENIE NA POŽIADANIE AKO VÝBER * FROM view_with_unionall;
Všimnite si, že pohľad view_with_unionall spĺňa požiadavky na rýchle obnovenie.
Každý blok dopytu v UNIONALL dotaz musí spĺňať požiadavky rýchleho obnoviteľného materializovaného zobrazenia s agregátmi alebo rýchlo obnoviteľného materializovaného zobrazenia so spojeniami.
Príslušné protokoly materializovaného zobrazenia musia byť vytvorené na tabuľkách, ako sa to vyžaduje pre zodpovedajúci typ rýchlo obnoviteľného materializovaného zobrazenia.
Všimnite si, že databáza Oracle umožňuje aj špeciálny prípad zhmotneného zobrazenia jednej tabuľky so spojeniami len za predpokladu, že ROWID stĺpec bol zahrnutý do SELECT zoznam a v denníku materializovaného zobrazenia. Toto je zobrazené v definujúcom dotaze pohľadu view_with_unionall.
SELECT zoznam každého dotazu musí obsahovať a UNIONALL značka a UNIONALL Každý stĺpec musí mať samostatnú konštantnú číselnú alebo reťazcovú hodnotu UNIONALL pobočka. Ďalej sa stĺpec značky musí objaviť v rovnakej poradovej polohe v SELECT zoznam každého bloku dotazu. Pozri "UNION ALL prepis značiek a dotazov» pre viac informácií o UNIONALL značkovače.
Niektoré funkcie, ako sú vonkajšie spojenia, len vložiť agregované dotazy materializovaného zobrazenia a vzdialené tabuľky nie sú podporované pre materializované zobrazenia s UNIONALL. Upozorňujeme však, že materializované zobrazenia používané pri replikácii, ktoré neobsahujú spojenia alebo agregáty, sa môžu rýchlo obnoviť, keď UNIONALL alebo sa používajú vzdialené stoly.
Parameter inicializácie kompatibility musí byť nastavený na 9.2.0 alebo vyšší, aby sa vytvoril rýchlo obnoviteľný materializovaný pohľad s UNIONALL.
Nechcem uraziť fanúšikov Oracle, ale súdiac podľa ich zoznamu obmedzení sa zdá, že tento mechanizmus nebol napísaný vo všeobecnom prípade pomocou nejakého modelu, ale tisíckami Indov, kde každý dostal príležitosť napísali svoju vlastnú vetvu a každý z nich urobil, čo mohol. Použitie tohto mechanizmu na skutočnú logiku je ako prechádzka mínovým poľom. Mínu môžete získať kedykoľvek stlačením jedného z nezrejmých obmedzení. Ako to funguje, je tiež samostatná otázka, ale to je nad rámec tohto článku.
Microsoft SQL Server
Ďalšie požiadavky
Okrem možností SET a požiadaviek na deterministické funkcie musia byť splnené nasledujúce požiadavky:
Používateľ, ktorý vykonáva CREATE INDEX musí byť vlastníkom zobrazenia.
Keď vytvoríte index, IGNORE_DUP_KEY musí byť nastavená na OFF (predvolené nastavenie).
Tabuľky musia byť odkazované dvojdielnymi názvami, schéma.názov tabuľky v definícii pohľadu.
Používateľom definované funkcie, na ktoré sa odkazuje v zobrazení, musia byť vytvorené pomocou WITH SCHEMABINDING možnosť.
Všetky používateľom definované funkcie, na ktoré sa odkazuje v zobrazení, musia byť odkazované dvojdielnymi názvami, ..
Vlastnosť prístupu k údajom funkcie definovanej používateľom musí byť NO SQLa vlastnosť externého prístupu musí byť NO.
Funkcie CLR (Common language runtime) sa môžu objaviť vo výberovom zozname zobrazenia, ale nemôžu byť súčasťou definície klastrovaného indexového kľúča. Funkcie CLR sa nemôžu objaviť v klauzule WHERE zobrazenia alebo v klauzule ON operácie JOIN v zobrazení.
Funkcie CLR a metódy užívateľom definovaných typov CLR použité v definícii pohľadu musia mať nastavené vlastnosti, ako je uvedené v nasledujúcej tabuľke.
Majetok
Poznámky
DETERMINISTICKÝ = PRAVDA
Musí byť explicitne deklarovaný ako atribút metódy Microsoft .NET Framework.
PRESNÉ = PRAVDA
Musí byť explicitne deklarovaný ako atribút metódy .NET Framework.
PRÍSTUP K ÚDAJOM = BEZ SQL
Určené nastavením atribútu DataAccess na DataAccessKind.None a atribútu SystemDataAccess na SystemDataAccessKind.None.
EXTERNÝ PRÍSTUP = NIE
Táto vlastnosť je štandardne nastavená na NO pre rutiny CLR.
Pohľad musí byť vytvorený pomocou WITH SCHEMABINDING možnosť.
Pohľad musí odkazovať len na základné tabuľky, ktoré sú v rovnakej databáze ako pohľad. Pohľad nemôže odkazovať na iné pohľady.
Príkaz SELECT v definícii pohľadu nesmie obsahovať nasledujúce prvky Transact-SQL:
COUNT
Funkcie ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, AND OPENXML) OUTER sa pripája (LEFT, RIGHT, Alebo FULL)
Odvodená tabuľka (definovaná zadaním a SELECT vyhlásenie v FROM doložka)
Vlastné spojenia
Určenie stĺpcov pomocou SELECT * or SELECT <table_name>.*
DISTINCT STDEV, STDEVP, VAR, VARP, Alebo AVG
Bežný tabuľkový výraz (CTE)
vznášať sa1, text, ntext, obraz, XML, Alebo filestream stĺpce
Poddotaz OVER klauzula, ktorá zahŕňa funkcie klasifikácie alebo agregácie okien
Fulltextové predikáty (CONTAINS, FREETEXT) SUM funkcia, ktorá odkazuje na výraz s možnosťou null ORDER BY
Používateľom definovaná agregačná funkcia CLR TOP CUBE, ROLLUP, Alebo GROUPING SETS Operátori
MIN, MAX UNION, EXCEPT, Alebo INTERSECT Operátori TABLESAMPLE
Tabuľkové premenné OUTER APPLY or CROSS APPLY PIVOT, UNPIVOT
Riedke sady stĺpcov
Vložené (TVF) alebo viacpríkazové tabuľkové funkcie (MSTVF) OFFSET
CHECKSUM_AGG
1 Indexované zobrazenie môže obsahovať vznášať sa stĺpce; takéto stĺpce však nemožno zahrnúť do klastrovaného indexového kľúča.
If GROUP BY je prítomná, definícia VIEW musí obsahovať COUNT_BIG(*) a nesmie obsahovať HAVING. Tieto GROUP BY obmedzenia sa vzťahujú len na definíciu indexovaného zobrazenia. Dotaz môže použiť indexované zobrazenie vo svojom pláne vykonávania, aj keď ich nespĺňa GROUP BY obmedzenia.
Ak definícia pohľadu obsahuje a GROUP BY klauzula, kľúč jedinečného klastrovaného indexu môže odkazovať iba na stĺpce špecifikované v GROUP BY klauzula.
Tu je jasné, že Indiáni neboli zapojení, pretože sa rozhodli urobiť to podľa schémy „urobíme málo, ale dobre“. To znamená, že majú na ihrisku viac mín, ale ich umiestnenie je transparentnejšie. Najviac sklamaním je toto obmedzenie:
Pohľad musí odkazovať len na základné tabuľky, ktoré sú v rovnakej databáze ako pohľad. Pohľad nemôže odkazovať na iné pohľady.
V našej terminológii to znamená, že funkcia nemôže pristupovať k inej materializovanej funkcii. To v zárodku obmedzuje všetku ideológiu.
Toto obmedzenie (a ďalej v texte) tiež výrazne znižuje prípady použitia:
Príkaz SELECT v definícii pohľadu nesmie obsahovať nasledujúce prvky Transact-SQL:
COUNT
Funkcie ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, AND OPENXML) OUTER sa pripája (LEFT, RIGHT, Alebo FULL)
Odvodená tabuľka (definovaná zadaním a SELECT vyhlásenie v FROM doložka)
Vlastné spojenia
Určenie stĺpcov pomocou SELECT * or SELECT <table_name>.*
DISTINCT STDEV, STDEVP, VAR, VARP, Alebo AVG
Bežný tabuľkový výraz (CTE)
vznášať sa1, text, ntext, obraz, XML, Alebo filestream stĺpce
Poddotaz OVER klauzula, ktorá zahŕňa funkcie klasifikácie alebo agregácie okien
Fulltextové predikáty (CONTAINS, FREETEXT) SUM funkcia, ktorá odkazuje na výraz s možnosťou null ORDER BY
Používateľom definovaná agregačná funkcia CLR TOP CUBE, ROLLUP, Alebo GROUPING SETS Operátori
MIN, MAX UNION, EXCEPT, Alebo INTERSECT Operátori TABLESAMPLE
Tabuľkové premenné OUTER APPLY or CROSS APPLY PIVOT, UNPIVOT
Riedke sady stĺpcov
Vložené (TVF) alebo viacpríkazové tabuľkové funkcie (MSTVF) OFFSET
CHECKSUM_AGG
OUTER JOINS, UNION, ORDER BY a iné sú zakázané. Možno by bolo jednoduchšie špecifikovať, čo by sa dalo použiť, ako to, čo sa použiť nedalo. Zoznam by bol pravdepodobne oveľa menší.
Aby som to zhrnul: obrovský súbor obmedzení v každej (všimnime si komerčnej) DBMS oproti žiadnej (s výnimkou jedného logického, nie technického) v technológii LGPL. Treba však poznamenať, že implementácia tohto mechanizmu v relačnej logike je o niečo náročnejšia ako v opísanej funkčnej logike.
Реализация
Ako to funguje? PostgreSQL sa používa ako „virtuálny stroj“. Vo vnútri je zložitý algoritmus, ktorý vytvára dotazy. Tu zdroj. A nejde len o veľký súbor heuristiky s množstvom if. Takže, ak máte pár mesiacov na štúdium, môžete skúsiť porozumieť architektúre.
Funguje to efektívne? Celkom efektívne. Bohužiaľ, je to ťažké dokázať. Môžem len povedať, že ak vezmete do úvahy tisíce požiadaviek, ktoré existujú vo veľkých aplikáciách, potom sú v priemere efektívnejšie ako požiadavky dobrého vývojára. Vynikajúci SQL programátor dokáže napísať akýkoľvek dotaz efektívnejšie, no pri tisíckach dotazov na to jednoducho nebude mať motiváciu ani čas. Jediná vec, ktorú teraz môžem uviesť ako dôkaz efektívnosti, je, že na platforme postavenej na tomto DBMS pracuje niekoľko projektov ERP systémy, ktoré majú tisíce rôznych MATERIALIZOVANÝCH funkcií, s tisíckami používateľov a terabajtovými databázami so stovkami miliónov záznamov bežiacich na bežnom dvojprocesorovom serveri. Účinnosť si však môže každý skontrolovať/vyvrátiť stiahnutím plošina a PostgreSQL, zapnutý protokolovanie SQL dotazov a pokus o zmenu logiky a údajov tam.
V nasledujúcich článkoch tiež porozprávam o tom, ako si môžete nastaviť obmedzenia funkcií, pracovať so zmenami a mnoho iného.