
V předchozím Popisoval jsem koncept a implementaci databáze založené na funkcích, nikoli na tabulkách a polích, jako v relačních databázích. Obsahovala mnoho příkladů, které ukazují výhody tohoto přístupu oproti klasickému. Mnozí je považovali za nedostatečně přesvědčivé.
V tomto článku ukážu, jak tento koncept umožňuje rychle a pohodlně vyvažovat zapisování a čtení do databáze bez jakýchkoli změn logiky. Podobnou funkcionalitu se pokusily realizovat moderní komerční SGBD (zejména Oracle a Microsoft SQL Server). Na konci článku ukážu, co se jim povedlo, mírně řečeno, ne příliš.
Popis
Jak jsem uvedl dříve, pro lepší pochopení začnu popisovat na příkladech. Předpokládejme, že potřebujeme realizovat logiku, která vrátí seznam oddělení s počtem zaměstnanců a jejich celkovým platem.
Ve funkční databázi by to vypadalo následovně:
CLASS Department 'Oddělení';
name 'Název' = DATA STRING[100] (Oddělení);
CLASS Employee ‘Zaměstnanec’;
department ‘Oddělení’ = DATA Department (Employee);
salary ‘Plat’ = DATA NUMERIC[10,2] (Employee);
countEmployees ‘Počet zaměstnanců’ (Department d) =
GROUP SUM 1 IF department(Employee e) = d;
salarySum ‘Celkový plat’ (Department d) =
GROUP SUM salary(Employee e) IF department(e) = d;
SELECT name(Department d), countEmployees(d), salarySum(d);
Složitost vykonání tohoto dotazu v jakémkoli SGBD bude ekvivalentní O(počet zaměstnanců), neboť k tomuto výpočtu je třeba proskenovat celou tabulku zaměstnanců a poté je seskupit podle oddělení. Také bude existovat nějaké malé (předpokládáme, že zaměstnanců je mnohem více než oddělení) zvýšení v závislosti na zvoleném plánu O(log počtu zaměstnanců) nebo O(počet oddělení) na seskupení a další.
Je jasné, že režijní náklady na vykonání se mohou lišit v různých SGBD, ale složitost se nijak nezmění.
V navržené implementaci funkční SGBD vytvoří jeden poddotaz, který vypočítá potřebné hodnoty podle oddělení, a poté provede JOIN s tabulkou oddělení pro získání názvu. Nicméně, při deklaraci každé funkce je možné zadat speciální značku MATERIALIZED. Systém automaticky vytvoří odpovídající pole pro každou takovou funkci. Při změně hodnoty funkce bude ve stejné transakci změněna i hodnota pole. Při volání této funkce se bude již obracet na předpočítané pole.
Zejména pokud je pro funkce nastavena možnost MATERIALIZED pocetZamestnancu a sumaMzdy, pak se do tabulky se seznamem oddělení přidají dvě pole, ve kterých budou uchovávány počty zaměstnanců a jejich celkové mzdy. Při jakékoli změně zaměstnanců, jejich mezd nebo příslušnosti k oddělením systém automaticky aktualizuje hodnoty těchto polí. Výše uvedený dotaz se pak bude obracet přímo na tato pole a bude proveden za O(počet oddělení).
Jaká jsou omezení? Pouze jedno: taková funkce musí mít konečný počet vstupních hodnot, pro které je její hodnota určena. Jinak nebude možné sestavit tabulku, která by uchovávala všechny její hodnoty, protože nemůže existovat tabulka s nekonečným počtem řádků.
Příklad:
employeesCount 'Počet zaměstnanců s platem > N' (oddělení d, NUMERIC[10,2] N) =
GROUP SUM plat(Employee e) IF oddělení(e) = d AND plat(e) > N;
Tato funkce je definována pro nekonečný počet hodnot čísla N (například jakákoli záporná hodnota). Proto ji nelze označit jako MATERIALIZED. To je tedy logické, nikoli technické omezení (tj. ne proto, že bychom to nedokázali implementovat). Jinak žádná omezení. Lze použít seskupování, řazení, AND a OR, PARTITION, rekurze atd.
Například v úloze 2.2 předchozího článku lze nastavit MATERIALIZED na obě funkce:
zakoupeno 'Zakoupil' (Zákazník c, Produkt p, CELOČÍSELNÉ y) =
SKUPINOVÁ SUMA suma(Detail d) POKUD
zákazník(příkaz(d)) = c A
produkt(d) = p A
extractYear(date(order(d))) = y MATERIALIZED;
hodnocení 'Hodnocení' (Zákazník c, Produkt p, CELOČÍSELNÉ y) =
PARTITION SUM 1 ORDER DESC bought(c, p, y), p BY c, y MATERIALIZED;
VYBERTE jménoKontaktu(Zákazník c), jméno(Produkt p) KDE hodnocení(c, p, 1997) < 3;
Systém automaticky vytvoří jednu tabulku s klíči typů Zákazník, Produkt a INTEGER, přidá do ní dvě pole a bude aktualizovat jejich hodnoty při jakýchkoli změnách. Při dalších voláních těchto funkcí nebude docházet k jejich výpočtu, ale budou se číst hodnoty z odpovídajících polí.
Pomocí tohoto mechanismu lze například eliminovat rekurze (CTE) v dotazech. Konkrétně zvažme skupiny, které vytvářejí strom pomocí vztahu child/parent (každá skupina má odkaz na svého rodiče):
rodič = DATA Skupina (Skupina);
V funkční databázi lze logiku rekurze definovat následujícím způsobem:
úroveň (skupina dítě, skupina rodič) = REKURZE 1l POKUD dítě JE Skupina A rodič == dítě
KROK 2l POKUD rodič == rodič($parent);
isParent (skupina dítě, skupina rodič) = PRAVDA POKUD úroveň(dítě, rodič) MATERIALIZOVANÁ;
Jelikož je pro funkci isParent nastaven MATERIALIZED, bude pod ní vytvořena tabulka se dvěma klíči (skupinami), ve které bude pole isParent pravdivé pouze tehdy, pokud je první klíč potomkem druhého. Počet záznamů v této tabulce bude roven počtu skupin vynásobenému průměrnou hloubkou stromu. Pokud je například třeba spočítat počet potomků určité skupiny, lze se obrátit na tuto funkci:
childrenCount (Group g) = GROUP SUM 1 IF isParent(Group child, g);
Žádné CTE v SQL dotazu přitom nebude. Místo toho dojde k jednoduchému GROUP BY.
Pomocí tohoto mechanismu lze také snadno provádět denormalizaci databáze podle potřeby:
CLASS Order 'Objednávka';
datum 'Datum' = DATA DATE (Objednávka);
CLASS OrderDetail 'Řádek objednávky';
order 'Objednávka' = DATA Order (OrderDetail);
date 'Datum' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;
Při volání funkce date pro řádek objednávky bude probíhat čtení z tabulky s řádky objednávek pole, pro které existuje index. Při změně data objednávky systém sám automaticky přepočítá denormalizované datum v řádku.
Výhody
K čemu je tento mechanismus potřebný? V klasických DBMS, bez přepisování dotazů, mohou vývojáři nebo DBA pouze měnit indexy, určovat statistiku a dávat plánovači dotazů rady, jak je vykonávat (přitom HINTy existují pouze v komerčních DBMS). Ať se snaží jakkoli, nebudou schopni první dotaz v článku provést za O (počet oddělení) bez změny dotazů a psaní triggerů. Ve navrhovaném schématu může vývojář v průběhu vývoje nerušeně přemýšlet o struktuře ukládání dat a o tom, jaké agregace použít. To všechno lze klidně měnit za běhu přímo v provozu.
V praxi to vypadá následovně. Někteří lidé vyvíjejí přímo logiku na základě zadaného úkolu. Nerozumí ani algoritmům a jejich složitosti, ani plánům vykonávání, ani typům joinů, ani žádné jiné technické části. Tito lidé jsou spíše byznys analytici než vývojáři. Poté všechno putuje do testování nebo provozu. Aktivuje se logování dlouhých dotazů. Když se zjistí dlouhý dotaz, rozhodnutí o zapnutí MATERIALIZED na nějaké mezifunkci je přijato jinými lidmi (více technickými — v podstatě DBA). Tím se mírně zpomalí zápis (protože je třeba aktualizovat další pole v transakci). Nicméně, výrazně se urychlí nejen tento dotaz, ale i všechny ostatní, které tuto funkci používají. Přitom je rozhodování o tom, kterou funkci materializovat, relativně jednoduché. Dva hlavní parametry: počet možných vstupních hodnot (přesně tolik záznamů bude v odpovídající tabulce) a jak často je používána v jiných funkcích.
Alternativy
V moderních komerčních DBMS existují podobné mechanismy: MATERIALIZED VIEW s FAST REFRESH (Oracle) a INDEXED VIEW (Microsoft SQL Server). V PostgreSQL MATERIALIZED VIEW není schopen se aktualizovat v transakci, pouze na vyžádání (a navíc s velmi přísnými omezeními), takže jej nebudeme zvažovat. Mají však několik problémů, které značně omezují jejich využití.
Za prvé, materializaci můžete zahrnout pouze tehdy, pokud jste již vytvořili běžný VIEW. Jinak budete muset přepsat ostatní dotazy pro přístup k nově vytvořenému zobrazení, abyste využili tuto materializaci. Nebo můžete všechno nechat, jak je, ale bude to minimálně neefektivní, pokud existují určité předpočítané údaje, které však ne všechny dotazy vždy využívají, ale vypočítávají znovu.
Za druhé, mají obrovské množství omezení:
Oracle
5.3.8.4 Obecná omezení na rychlé obnovení
Definující dotaz materializovaného zobrazení je omezen následujícím způsobem:
- Materializované zobrazení nesmí obsahovat odkazy na neopakující se výrazy jako
SYSDATEandROWNUM.- Materializované zobrazení nesmí obsahovat odkazy na
RAWorLONGRAWdatové typy.- Nesmí obsahovat
nebude prováděn při nepravdivosti první podmínky. Opravy pomocípoddotaz z seznamu.- Nesmí obsahovat analytické funkce (například,
RANK) vnebude prováděn při nepravdivosti první podmínky. Opravy pomocíklauzuli.- Nesmí odkazovat na tabulku, na které je definován
XMLIndexindex.- Nesmí obsahovat
MODELklauzuli.- Nesmí obsahovat
klauzule s poddotazem.Nesmí obsahovat vnořené dotazy, které mají- , nebo
Zní to poněkud šíleně, ale na schématu — je to jednoduché.,ALL[START WITH …] CONNECT BYNOTEXISTS.- Nesmí obsahovat
Nesmí obsahovat více detailních tabulek na různých místech.klauzuli.- Materializovaná zobrazení nemohou mít vzdálené detailní tabulky.
NACOMMITVnořená materializovaná zobrazení musí mít spojení nebo agregaci.- Materializovaná spojení a materializované agregační pohledy s
- GROUP
BYklauzulí nemohou vybírat z tabulky organizované podle indexu.5.3.8.5 Omezení na rychlé obnovení u materializovaných zobrazení pouze se spojiDefinující dotazy pro materializovaná zobrazení pouze se spoji a bez agregací mají následující omezení na rychlé obnovení:
Všechna omezení z „
- Obecná omezení na rychlé obnovení«.
- klauzule nebo agregace.
BYklauzulí nemohou vybírat z tabulky organizované podle indexu.Rowid všech tabulek v- seznamu musí být uveden v
FROMseznamu dotazu.nebude prováděn při nepravdivosti první podmínky. Opravy pomocíLogy materiálového zobrazení musí existovat s rowid pro všechny základní tabulky v- Není možné vytvořit materializované zobrazení obnovitelné rychle z více tabulek s jednoduchými spoji, které zahrnují sloupec typu objektu v
FROMLogy materiálového zobrazení musí existovat s rowid pro všechny základní tabulky v- prohlášení.
nebude prováděn při nepravdivosti první podmínky. Opravy pomocíTaké metoda obnovení, kterou si vyberete, nebude optimálně efektivní, pokud:Definující dotaz používá vnější spojení, které se chová jako vnitřní spojení. Pokud definující dotaz obsahuje takové spojení, zvažte přepsání definujícího dotazu na vnitřní spojení.
- seznam materializovaného zobrazení obsahuje výrazy na sloupcích z více tabulek.
- The
nebude prováděn při nepravdivosti první podmínky. Opravy pomocí5.3.8.6 Omezení na rychlé obnovení u materializovaných zobrazení s agregacemiDefinující dotazy pro materializovaná zobrazení s agregacemi nebo spoji mají následující omezení na rychlé obnovení:
Rychlé obnovení je podporováno pro oba
- Obecná omezení na rychlé obnovení«.
DEMAND
NACOMMITandNAmaterializované zobrazení, nicméně platí následující omezení:Všechny tabulky v materializovaném zobrazení musí mít logy materializovaného zobrazení a logy materializovaného zobrazení musí:
- Obsahovat všechny sloupce z tabulky uvedené v materializovaném zobrazení.
- Uvedeno s
- ROWID
ZAHŔNUJÍCÍandNOVÉUveďte klauzuli, pokud se očekává, že tabulka bude mít směs vkládání/přímého načítání, mazání a aktualizací.VALUES.- Pouze
SEQUENCESUM- STDDEV
VARIANCE,COUNT,AVG,MAX,jsou podporovány pro rychlé obnovení.,MINandCOUNT(*)musí být uvedeno.COUNT(*)must be specified.- Agregační funkce mohou být použity pouze jako nejvnější část výrazu. To znamená, že agregáty jako
AVG(AVG(x))orAVG(x)+AVG(x)nejsou povoleny.- Pro každý agregát, jako je
AVG(expr), musí být přítomno odpovídajícíCOUNT(expr). Společnost Oracle doporučuje, abySUM(expr)byla určena.- Pokud
VARIANCE(expr)orSTDDEV(expr) je určena,COUNT(expr)andSUM(expr)musí být určena. Společnost Oracle doporučuje, abySUM(expr * expr)byla určena.- The
nebude prováděn při nepravdivosti první podmínky. Opravy pomocísloupec v definujícím dotazu nemůže být komplexním výrazem s sloupci z více základních tabulek. Možným řešením je použít vnořený materializovaný pohled.- The
nebude prováděn při nepravdivosti první podmínky. Opravy pomocíseznam musí obsahovat všechnyBYklauzulí nemohou vybírat z tabulky organizované podle indexu.sloupce.- Materializovaný pohled není založen na jedné nebo více vzdálených tabulkách.
- Pokud používáte
CHARdatový typ ve filtračních sloupcích protokolu materializovaného pohledu, znakové sady hlavního místa a materializovaného pohledu musí být stejné.- Pokud má materializovaný pohled jedno z následujících, pak je rychlé obnovení podporováno pouze u konvenčních DML vkládání a přímých načtení.
- Materializované pohledy s
MINorCOUNT(*)agregáty- Materializované pohledy, které mají
SUM(expr)ale nemajíCOUNT(expr)- Materializované pohledy bez
COUNT(*)Takový materializovaný pohled se nazývá pouze vkládací materializovaný pohled.
- Materializovaný pohled s
COUNT(*)orMINje rychle obnovitelný po odstranění nebo smíšených DML příkazech, pokud nemánení spolehlivý:klauzuli.
Max/min rychlé obnovení po odstranění nebo smíšeném DML nemá stejné chování jako případ pouze vkládající. Odstraní a přepočítá maximální/minimální hodnoty pro dotčené skupiny. Musíte být obezřetní vůči dopadu na výkon.- Materializované pohledy s pojmenovanými pohledy nebo poddotazy v
FROMklauzuli mohou být rychle obnovitelné, pokud lze pohledy zcela sloučit. Informace o tom, které pohledy se sloučí, naleznete v .- Pokud nejsou žádné vnější spojení, můžete mít libovolné výběry a spojení v
není spolehlivý:klauzuli.- Materializované agregační pohledy s vnějšími spojeními jsou rychle obnovitelné po konvenčním DML a přímých načteních, pokud byla upravena pouze vnější tabulka. Také musí existovat jedinečné omezení na spojovacích sloupcích tabulky s vnitřním spojení. Pokud jsou zde vnější spojení, všechna spojení musí být spojena pomocí
As a musí používat rovnost (=) operátor.- Pro materializované pohledy s
CUBE,ROLLUP, skupinové sady nebo jejich spojení platí následující omezení:
- The
nebude prováděn při nepravdivosti první podmínky. Opravy pomocíseznam by měl obsahovat skupinový rozlišovač, který může být buďGROUPING_IDfunkcí pro všechnyBYklauzulí nemohou vybírat z tabulky organizované podle indexu.výrazy neboGROUPINGfunkcemi, každou pro každýBYklauzulí nemohou vybírat z tabulky organizované podle indexu.výraz. Například, pokud klauzule materializovaného pohledu je „BYklauzulí nemohou vybírat z tabulky organizované podle indexu.CUBE(a, b)BYklauzulí nemohou vybírat z tabulky organizované podle indexu.“, pak by měl seznam obsahovat buď „GROUPING_ID(a, b)nebude prováděn při nepravdivosti první podmínky. Opravy pomocí“ nebo „GROUPING(a)GROUPING(b)“ pro to, aby byl materializovaný pohled rychle obnovitelný.Aby neměl vést k žádným duplicitním skupinám. Například, „GROUP BY a, ROLLUP(a, b)BYklauzulí nemohou vybírat z tabulky organizované podle indexu.“ není rychle obnovitelné, protože vede k duplicitním skupinám „(a), (a, b) A (a)5.3.8.7 Omezení na rychlé obnovení u materializovaných pohledů s UNION ALLMaterializované pohledy s«.operátorem množiny podporují
REFRESH
UNIONALLFASTmožnost, pokud jsou splněny následující podmínky:Definující dotaz musí mítoperátor na nejvyšší úrovni.
- operátor nemůže být vložen do poddotazu, s jednou výjimkou: "
UNIONALLmůže být v poddotazu vThe
UNIONALLklauzuli, pokud je definující dotaz ve tvaruUNIONALLSELECT * FROMFROM(pohled nebo poddotaz s) jako v následujícím příkladu: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_name = 'Jones');CREATE MATERIALIZED VIEW unionall_inside_view_mv REFRESH FAST ON DEMAND AS SELECT * FROM view_with_unionall;UNIONALLVšimněte si, že pohledview_with_unionallsplňuje požadavky na rychlé obnovení.
Každý blok dotazu vdotazu musí splňovat požadavky rychle obnovitelného materializovaného pohledu s agregáty nebo rychle obnovitelného materializovaného pohledu s spojeními.- Musí být vytvořeny odpovídající protokoly materializovaného pohledu na tabulkách, jak je požadováno pro odpovídající typ rychle obnovitelného materializovaného pohledu.
UNIONALLquery must satisfy the requirements of a fast refreshable materialized view with aggregates or a fast refreshable materialized view with joins.The appropriate materialized view logs must be created on the tables as required for the corresponding type of fast refreshable materialized view.
Všimněte si, že Oracle Database také umožňuje zvláštní případ jediné materializované pohledy na tabulku s pouze spojeními, pokud je sloupec zahrnut vZAHŔNUJÍCÍseznamu a v deníku materializovaného pohledu. To je zobrazeno v definičním dotazu pohledunebude prováděn při nepravdivosti první podmínky. Opravy pomocíseznam každého dotazu musí zahrnovatKaždý blok dotazu v.- The
nebude prováděn při nepravdivosti první podmínky. Opravy pomocíznačku a sloupec musí mít odlišnou konstantní numerickou nebo textovou hodnotu v každéUNIONALLvětvi. Dále, sloupec značky musí být ve stejné pořadí vUNIONALLseznamu každého bloku dotazu. Viz «UNIONALLUNION ALL Značka a Přepis dotazunebude prováděn při nepravdivosti první podmínky. Opravy pomocí» pro více informací ohledněNěkteré funkce jako vnější spojení, dotazy s agregovanými materializovanými pohledy pouze pro vkládání a vzdálené tabulky nejsou podporovány pro materializované pohledy sUNIONALL. Nezapomeňte však, že materializované pohledy používající replikaci, které neobsahují spojení nebo agregace, lze rychle obnovit, pokud- nebo vzdálené tabulky jsou použity.
UNIONALLParametr inicializace kompatibility musí být nastaven na 9.2.0 nebo vyšší pro vytvoření rychle obnovitelného materializovaného pohledu sUNIONALLNechci urazit fanoušky Oracle, ale podle jejich seznamu omezení to vypadá, že tento mechanismus byl napsán ne z pohledu obecného případu, s použitím nějakého modelu, ale tisíci Indy, kde každý měl napsat svou vlastní větev a každý z nich udělal, co mohl. Používání tohoto mechanismu pro skutečnou logiku je jako chůze po minovém poli. V každém okamžiku můžete narazit na minu, když se dotknete jednoho z ne zcela zjevného omezení. Jak to funguje — to je také samostatná otázka, ale ta je mimo rámec tohoto článku.- Dodatečné požadavky
UNIONALL.
Kromě požadavků na nastavení parametrů a deterministických funkcí je třeba splnit následující požadavky:
Microsoft SQL Server
Uživatel, který vykonává
musí být vlastníkem pohledu.
- Při vytváření indexu musí být možnost
CREATE INDEXIGNORE_DUP_KEY- nastavena na VYPNUTO (výchozí nastavení).
Tabulky musí být odkazovány pomocí dvoudílných názvů,tablename- v definici pohledu. schema.Uživatelsky definované funkce odkazované v pohledu musí být vytvořeny pomocí WITH SCHEMABINDING
- možnost.
Jakékoli uživatelsky definované funkce odkazované v pohledu musí být odkazovány pomocí dvoudílných názvů,<schema>- <function> Datový přístup vlastnost uživatelsky definované funkce musí být.NO SQL.
- , a externí přístupová vlastnost musí být
NOFunkce běhového prostředí společného jazyka (CLR) mohou být uvedeny v seznamu výběru pohledu, ale nemohou být součástí definice klíče clustered indexu. Funkce CLR nesmějí být uvedeny v klauzuli WHERE pohledu nebo v klauzuli ON operace JOIN v pohledu.Funkce CLR a metody CLR uživatelsky definovaných typů použité v definici pohledu musí mít nastaveny vlastnosti tak, jak je uvedeno v následující tabulce..- DETERMINISTIC = TRUE
- Musí být výslovně deklarováno jako atribut metody Microsoft .NET Framework.
Vlastnost
NotePRECISE = TRUE
Musí být výslovně deklarováno jako atribut metody .NET Framework.DATA ACCESS = NO SQL
Určeno nastavením atributu DataAccess na DataAccessKind.None a atributu SystemDataAccess na SystemDataAccessKind.None.EXTERNAL ACCESS = NO
Tato vlastnost ve výchozím nastavení je NO pro CLR rutiny.Pohled musí být vytvořen pomocí
Pohled musí odkazovat pouze na základní tabulky, které jsou ve stejné databázi jako pohled. Pohled nesmí odkazovat na jiné pohledy.- Dotaz SELECT v definici pohledu nesmí obsahovat následující prvky Transact-SQL:
Jakékoli uživatelsky definované funkce odkazované v pohledu musí být odkazovány pomocí dvoudílných názvů,<schema>- Funkce ROWSET (
- OPENDATASOURCE
COUNT
OPENQUERYOPENROWSET,, A,OPENXMLVnějšíspojení ()
LEVÝPRAVÝPLNÝ,Odvozená tabulka (definovaná specifikováním[START WITH …] CONNECT BYpředpisu v klauzuli))Sebezapojení
nebude prováděn při nepravdivosti první podmínky. Opravy pomocíSpecifikování sloupců pomocíFROMSELECT *
SELECT <table_name>.*
STDEVSTDEVPorVAR
DISTINCT
VARP,Společný tabulkový výraz (CTE),ntext,ntext[START WITH …] CONNECT BYAVG
ntextfloat1, text, ntext, obrázek, XML[START WITH …] CONNECT BY filestream sloupce
Poddotaz
NADklauzule, která zahrnuje hodnotící nebo agregační oknové funkcePredikáty pro úplný text (
OBSAHUJE,FREETEXT)
VARIANCEfunkce, která odkazuje na nullable výraz
ORDER BYCLR uživatelsky definovaná agregační funkce
TOP
CUBE,ROLLUP[START WITH …] CONNECT BYSADY SKUPINOVÁNÍoperátory
MIN,COUNT(*)
UNION,KROMĚ[START WITH …] CONNECT BYINTERSECToperátory
VZOREK TABULKYTabulkové proměnné
VONNÝ APLIKACEorCROSS APPLY
PIVOT,UNPIVOTSady sparse sloupců
Inline (TVF) nebo více-statement table-valued funkce (MSTVF)
OFFSET
CHECKSUM_AGG1 Indexovaný pohled může obsahovat float sloupce; nicméně takové sloupce nemohou být zahrnuty do klíče clustered indexu.
- Pokud
GROUP BYje-li přítomen, definice VIEW musí obsahovatCOUNT_BIG(*)a nesmí obsahovatklauzule s poddotazem.. TytoGROUP BYomezení se vztahují pouze na definici indexovaného pohledu. Dotaz může použít indexovaný pohled v jeho plánování exekuce, i když tatoGROUP BYomezení. Pokud definice pohledu obsahuje- klauzuli, může klíč unikátního clustered indexu odkazovat pouze na sloupce uvedené v
GROUP BYJe jasné, že Indy to nezajímalo, protože se rozhodli udělat to podle schématu "uděláme málo, ale dobře". To znamená, že mají více min na poli, ale jejich umístění je transparentnější. Nejvíce mrzí toto omezení:GROUP BYklauzuli.
V naší terminologii to znamená, že funkce nemůže odkazovat na jinou materializovanou funkci. To podkopává celou ideologii.
Funkce ROWSET (
Toto omezení (a dále v textu) značně snižuje možnosti použití:
Zakázány jsou OUTER JOINS, UNION, ORDER BY a další. Možná by bylo jednodušší uvést, co lze použít, než to, co nelze. Seznam by pravděpodobně byl mnohem menší.
OPENDATASOURCE
COUNT
OPENQUERYOPENROWSET,, A,OPENXMLVnějšíspojení ()
LEVÝPRAVÝPLNÝ,Odvozená tabulka (definovaná specifikováním[START WITH …] CONNECT BYpředpisu v klauzuli))Sebezapojení
nebude prováděn při nepravdivosti první podmínky. Opravy pomocíSpecifikování sloupců pomocíFROMSELECT *
SELECT <table_name>.*
STDEVSTDEVPorVAR
DISTINCT
VARP,Společný tabulkový výraz (CTE),ntext,ntext[START WITH …] CONNECT BYAVG
ntextfloat1, text, ntext, obrázek, XML[START WITH …] CONNECT BY filestream sloupce
Poddotaz
NADklauzule, která zahrnuje hodnotící nebo agregační oknové funkcePredikáty pro úplný text (
OBSAHUJE,FREETEXT)
VARIANCEfunkce, která odkazuje na nullable výraz
ORDER BYCLR uživatelsky definovaná agregační funkce
TOP
CUBE,ROLLUP[START WITH …] CONNECT BYSADY SKUPINOVÁNÍoperátory
MIN,COUNT(*)
UNION,KROMĚ[START WITH …] CONNECT BYINTERSECToperátory
VZOREK TABULKYTabulkové proměnné
VONNÝ APLIKACEorCROSS APPLY
PIVOT,UNPIVOTSady sparse sloupců
Inline (TVF) nebo více-statement table-valued funkce (MSTVF)
OFFSET
CHECKSUM_AGG
Ve zjednodušeném závěru: obrovský soubor omezení v každé (zdůrazňuji obchodní) DBMS vs. žádná (kromě jednoho logického, nikoli technického) v LGPL technologii. Je však třeba poznamenat, že implementace tohoto mechanismu v relační logice je poněkud složitější než v popsané funkční.
Jak to funguje? Jako "virtuální stroj" se používá PostgreSQL. Uvnitř existuje složitý algoritmus, který se zabývá sestavováním dotazů. Tady
Implementace
. A tam není jen velké množství heuristik s hromadou if'ů. Takže, pokud máte pár měsíců na studium, můžete to zkusit pochopit architekturu. . И там не просто большой набор эвристик с кучей if’ов. Так что, если есть пару месяцев на изучение, то можете попробовать разобраться в архитектуре.
Funguje to efektivně? Dostatečně efektivně. Bohužel, důkaz toho je těžký. Mohu jen říci, že když vezmete v úvahu tisíce dotazů, které existují ve velkých aplikacích, tak průměrně jsou efektivnější než u dobrého vývojáře. Skvělý SQL programátor může napsat jakýkoli dotaz efektivněji, ale u tisíce dotazů nemá motivaci ani čas to udělat. Jediné, co mohu nyní uvést jako důkaz efektivity, je to, že na platformě postavené na této DBMS běží několik projektů , ve kterých je tisíce různých MATERIALIZED funkcí, s tisíci uživateli a terabajtovými databázemi se stovkami milionů záznamů, které běží na běžném dvouprocesorovém serveru. Každý, kdo chce, může efektivitu ověřit/vyvrátit stažením a PostgreSQL, logováním SQL dotazů a pokusit se změnit logiku a data tam.
V následujících článcích také povím o tom, jak lze omezit funkce, pracovat se sezeními změn a mnohem více.
Zdroj: habr.com
