V prejšnjem članek Opisal sem koncept in izvedbo baze podatkov, zgrajene na podlagi funkcij, ne pa tabel in polj kot v relacijskih bazah podatkov. Podal je številne primere, ki kažejo prednosti tega pristopa pred klasičnim. Mnogi so se zdeli premalo prepričljivi.
V tem članku bom pokazal, kako vam ta koncept omogoča hitro in priročno uravnoteženje pisanja in branja v bazo podatkov brez kakršne koli spremembe logike delovanja. Podobno funkcionalnost so poskušali implementirati v sodobne komercialne DBMS (zlasti Oracle in Microsoft SQL Server). Na koncu članka bom pokazal, da se to, kar so naredili, milo rečeno, ni najbolje obneslo.
Opis
Kot prej bom za boljše razumevanje opis začel s primeri. Recimo, da moramo implementirati logiko, ki bo vrnila seznam oddelkov s številom zaposlenih v njih in njihovo skupno plačo.
V funkcionalni bazi podatkov bi to izgledalo takole:
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;
Kompleksnost izvajanja te poizvedbe v kateri koli DBMS bo enakovredna O (število zaposlenih)ker ta izračun zahteva skeniranje celotne tabele zaposlenih in njihovo nato grupiranje po oddelkih. Glede na izbrani načrt bo na voljo tudi nekaj malega (verjamemo, da je zaposlenih veliko več kot oddelkov). O(log število zaposlenih) ali O (število oddelkov) za združevanje in tako naprej.
Jasno je, da so stroški izvajanja lahko različni v različnih DBMS, vendar se kompleksnost ne bo spremenila na noben način.
V predlagani izvedbi bo funkcionalni DBMS ustvaril eno podpoizvedbo, ki bo izračunala zahtevane vrednosti za oddelek, nato pa naredila JOIN s tabelo oddelka, da bi pridobila ime. Za vsako funkcijo pa je ob deklaraciji možno nastaviti poseben označevalec MATERIALIZED. Sistem bo za vsako tako funkcijo samodejno ustvaril ustrezno polje. Ko spremenite vrednost funkcije, se bo v isti transakciji spremenila tudi vrednost polja. Ko dostopate do te funkcije, se dostopa do vnaprej izračunanega polja.
Še posebej, če za funkcije nastavite MATERIALIZED countEmployees и plačaSum, nato pa bosta tabeli s seznamom oddelkov dodani dve polji, v katerih bo shranjeno število zaposlenih in njihova skupna plača. Kadar koli pride do spremembe zaposlenih, njihovih plač ali pripadnosti oddelku, bo sistem samodejno spremenil vrednosti teh polj. Zgornja poizvedba bo neposredno dostopala do teh polj in bo izvedena v O (število oddelkov).
Kakšne so omejitve? Samo ena stvar: takšna funkcija mora imeti končno število vhodnih vrednosti, za katere je definirana njena vrednost. V nasprotnem primeru bo nemogoče sestaviti tabelo, ki bi hranila vse svoje vrednosti, saj ne more obstajati tabela z neskončnim številom vrstic.
Primer:
employeesCount ‘Количество сотрудников с зарплатой > N’ (Department d, NUMERIC[10,2] N) =
GROUP SUM salary(Employee e) IF department(e) = d AND salary(e) > N;
Ta funkcija je definirana za neskončno število vrednosti N (primerna je na primer katera koli negativna vrednost). Zato nanj ne morete postaviti MATERIALIZIRANO. To je torej logična omejitev, ne tehnična (torej ne zato, ker je ne bi mogli implementirati). Sicer pa ni nobenih omejitev. Uporabite lahko združevanje, razvrščanje, IN in ALI, PARTICIJO, rekurzijo itd.
Na primer, v problemu 2.2 prejšnjega članka lahko postavite MATERIALIZED na obe funkciji:
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;
Sistem bo sam ustvaril eno tabelo s tipskimi ključi Pomoč, Izdelek и CELO, mu bo dodal dve polji in z morebitnimi spremembami posodobil vrednosti polj v njih. Pri nadaljnjih klicih teh funkcij ne bodo izračunane, temveč bodo vrednosti prebrane iz ustreznih polj.
S tem mehanizmom se lahko na primer znebite rekurzij (CTE) v poizvedbah. Predvsem razmislite o skupinah, ki tvorijo drevo z odnosom otrok/starš (vsaka skupina ima povezavo do svojega starša):
parent = DATA Group (Group);
V funkcionalni bazi podatkov je rekurzijsko logiko mogoče podati na naslednji način:
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;
Ker za funkcijo isParent je označeno z MATERIALIZIRANO, potem se bo zanj ustvarila tabela z dvema ključema (skupinama), v kateri bo polje isParent bo resničen samo, če je prvi ključ otrok drugega. Število vnosov v tej tabeli bo enako številu skupin, pomnoženemu s povprečno globino drevesa. Če želite na primer prešteti število potomcev določene skupine, lahko uporabite to funkcijo:
childrenCount (Group g) = GROUP SUM 1 IF isParent(Group child, g);
V poizvedbi SQL ne bo CTE. Namesto tega bo na voljo preprosto GROUP BY.
S tem mehanizmom lahko po potrebi preprosto denormalizirate bazo podatkov:
CLASS Order 'Заказ';
date 'Дата' = DATA DATE (Order);
CLASS OrderDetail 'Строка заказа';
order 'Заказ' = DATA Order (OrderDetail);
date 'Дата' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;
Pri klicu funkcije Datum za naročilno vrstico bo polje, za katerega obstaja indeks, prebrano iz tabele z naročilnimi vrsticami. Ko se datum naročila spremeni, bo sistem sam samodejno preračunal denormalizirani datum v vrstici.
Prednosti
Čemu je namenjen ves ta mehanizem? V klasičnih DBMS lahko brez prepisovanja poizvedb razvijalec ali DBA samo spremeni indekse, določi statistiko in načrtovalcu poizvedb pove, kako naj jih izvede (namigi pa so na voljo samo v komercialnih DBMS). Ne glede na to, koliko se trudijo, ne bodo mogli dokončati prve poizvedbe v članku v O (število oddelkov) brez spreminjanja poizvedb ali dodajanja sprožilcev. V predlagani shemi vam na stopnji razvoja ni treba razmišljati o strukturi shranjevanja podatkov in o tem, katere agregacije uporabiti. Vse to je mogoče enostavno spremeniti sproti, neposredno med delovanjem.
V praksi je videti takole. Nekateri ljudje razvijejo logiko neposredno na podlagi naloge. Ne razumejo algoritmov in njihove kompleksnosti, niti izvedbenih načrtov, niti tipov povezav, niti katere koli druge tehnične komponente. Ti ljudje so bolj poslovni analitiki kot razvijalci. Nato gre vse to v testiranje ali delovanje. Omogoča beleženje dolgotrajnih poizvedb. Ko je zaznana dolga poizvedba, se drugi ljudje (bolj tehnični - v bistvu DBA) odločijo omogočiti MATERIALIZED na neki vmesni funkciji. To nekoliko upočasni snemanje (saj zahteva posodobitev dodatnega polja v transakciji). Vendar pa ni bistveno pohitrena samo ta poizvedba, ampak tudi vse ostale, ki to funkcijo uporabljajo. Hkrati je odločitev, katero funkcijo uresničiti, relativno enostavna. Dva glavna parametra: število možnih vhodnih vrednosti (to je, koliko zapisov bo v ustrezni tabeli) in kako pogosto se uporablja v drugih funkcijah.
Analogi
Sodobni komercialni DBMS-ji imajo podobne mehanizme: MATERIALIZIRANI POGLED s HITRO OSVEŽEVANJEM (Oracle) in INDEKSIRAN POGLED (Microsoft SQL Server). V PostgreSQL MATERIALIZED VIEW ni mogoče posodobiti v transakciji, ampak samo na zahtevo (in celo z zelo strogimi omejitvami), zato ga ne upoštevamo. Imajo pa več težav, ki bistveno omejujejo njihovo uporabo.
Prvič, materializacijo lahko omogočite le, če ste že ustvarili običajni POGLED. V nasprotnem primeru boste morali za uporabo te materializacije prepisati preostale zahteve za dostop do novo ustvarjenega pogleda. Ali pa pustite vse tako, kot je, vendar bo vsaj neučinkovito, če obstajajo določeni že vnaprej izračunani podatki, vendar jih veliko poizvedb ne uporablja vedno, ampak jih preračuna.
Drugič, imajo ogromno omejitev:
Oracle
5.3.8.4 Splošne omejitve za hitro osveževanje
Definirajoča poizvedba materializiranega pogleda je omejena na naslednji način:
Materializirani pogled ne sme vsebovati sklicevanj na izraze, ki se ne ponavljajo, kot je SYSDATE in ROWNUM.
Materializirani pogled ne sme vsebovati referenc na RAW or LONGRAW vrste podatkov.
Ne more vsebovati a SELECT seznam podpoizvedbe.
Ne more vsebovati analitičnih funkcij (npr. RANK) v SELECT klavzula.
Ne more se sklicevati na tabelo, na kateri je an XMLIndex indeks je določen.
Ne more vsebovati a MODEL klavzula.
Ne more vsebovati a HAVING stavek s podpoizvedbo.
Ne more vsebovati ugnezdenih poizvedb, ki imajo ANY, ALLali NOTEXISTS.
Ne more vsebovati a [START WITH …] CONNECT BY klavzula.
Ne more vsebovati več tabel s podrobnostmi na različnih mestih.
ONCOMMIT materializirani pogledi ne morejo imeti tabel oddaljenih podrobnosti.
Ugnezdeni materializirani pogledi morajo imeti spoj ali agregat.
Materializirani združeni pogledi in materializirani združeni pogledi z a GROUPBY člena ni mogoče izbrati iz tabele, urejene z indeksom.
5.3.8.5 Omejitve hitrega osveževanja materializiranih pogledov samo z združitvami
Definiranje poizvedb za materializirane poglede samo z združitvami in brez agregatov ima naslednje omejitve pri hitrem osveževanju:
Vrstice vseh tabel v FROM seznam mora biti prikazan v SELECT seznam poizvedbe.
Dnevniki materializiranega pogleda morajo obstajati z vrsticami za vse osnovne tabele v FROM seznam poizvedbe.
Ne morete ustvariti materializiranega pogleda s hitrim osveževanjem iz več tabel s preprostimi spoji, ki vključujejo stolpec vrste predmeta v SELECT izjavo.
Prav tako izbrani način osveževanja ne bo optimalno učinkovit, če:
Definirajoča poizvedba uporablja zunanjo združitev, ki se obnaša kot notranja združitev. Če definirajoča poizvedba vsebuje tako združevanje, razmislite o prepisu definirajoče poizvedbe, da bo vsebovala notranje združevanje.
O SELECT seznam materializiranega pogleda vsebuje izraze za stolpce iz več tabel.
5.3.8.6 Omejitve hitrega osveževanja materializiranih pogledov z agregati
Definiranje poizvedb za materializirane poglede z agregati ali spoji ima naslednje omejitve pri hitrem osveževanju:
Hitro osveževanje je podprto za oba ONCOMMIT in ONDEMAND materializirani pogledi, vendar veljajo naslednje omejitve:
Vse tabele v materializiranem pogledu morajo imeti dnevnike materializiranega pogleda, dnevniki materializiranega pogleda pa morajo:
Vsebuje vse stolpce iz tabele, na katero se sklicuje materializiran pogled.
Določite z ROWID in INCLUDINGNEWVALUES.
določite SEQUENCE če se pričakuje, da bo tabela vsebovala mešanico vstavljanj/neposrednih nalaganj, brisanja in posodobitev.
samo SUM, COUNT, AVG, STDDEV, VARIANCE, MIN in MAX so podprti za hitro osveževanje.
COUNT(*) je treba navesti.
Združevalne funkcije se morajo pojaviti le kot najbolj oddaljeni del izraza. Se pravi agregati kot npr AVG(AVG(x)) or AVG(x)+ AVG(x) niso dovoljene.
Za vsak agregat kot npr AVG(expr), ustrezna COUNT(expr) mora biti prisoten. Oracle to priporoča SUM(expr) določiti.
If VARIANCE(expr) or STDDEV(expr) je določeno, COUNT(expr) in SUM(expr) je treba navesti. Oracle to priporoča SUM(expr *expr) določiti.
O SELECT stolpec v definirajoči poizvedbi ne more biti zapleten izraz s stolpci iz več osnovnih tabel. Možna rešitev za to je uporaba ugnezdenega materializiranega pogleda.
O SELECT seznam mora vsebovati vse GROUPBY stolpcev.
Materializirani pogled ne temelji na eni ali več oddaljenih tabelah.
Če uporabljate a CHAR tipa podatkov v stolpcih filtra dnevnika materializiranega pogleda, morajo biti nabori znakov glavnega mesta in materializiranega pogleda enaki.
Če ima materializiran pogled eno od naslednjega, je hitro osveževanje podprto samo pri običajnih vstavkih DML in neposrednih nalaganjih.
Materializirani pogledi z MIN or MAX agregati
Materializirani pogledi, ki imajo SUM(expr) vendar ne COUNT(expr)
Materializirani pogledi brez COUNT(*)
Takšen materializiran pogled se imenuje materializiran pogled samo za vstavljanje.
Materializiran pogled z MAX or MIN se hitro osveži po izbrisu ali mešanih stavkih DML, če nima a WHERE klavzula.
Največja/najmanjša hitra osvežitev po brisanju ali mešanem DML nima enakega vedenja kot primer samo vstavi. Izbriše in znova izračuna največje/najmanjše vrednosti za prizadete skupine. Zavedati se morate njegovega vpliva na uspešnost.
Materializirani pogledi z imenovanimi pogledi ali podpoizvedbami v FROM klavzulo je mogoče hitro osvežiti, če je mogoče poglede popolnoma združiti. Za informacije o tem, kateri pogledi se bodo združili, glejte Oracle Database SQL Reference Language.
Če ni zunanjih združevanj, imate morda poljubne izbire in združevanja v WHERE klavzula.
Materializirane agregatne poglede z zunanjimi spoji je mogoče hitro osvežiti po običajnem DML in neposrednih nalaganjih, če je bila spremenjena samo zunanja tabela. Prav tako morajo obstajati enolične omejitve za spojene stolpce notranje tabele za spajanje. Če obstajajo zunanji spoji, morajo biti vsi spoji povezani z ANDs in mora uporabiti enakost (=) operater.
Za materializirane poglede z CUBE, ROLLUP, združevanje nizov ali njihovo veriženje veljajo naslednje omejitve:
O SELECT seznam mora vsebovati razločevalnik združevanja, ki je lahko a GROUPING_ID delujejo na vseh GROUPBY izrazi oz GROUPING funkcije po eno za vsakega GROUPBY izražanje. Na primer, če je GROUPBY klavzula materializiranega pogleda je "GROUPBYCUBE(a, b)", nato pa SELECT seznam mora vsebovati "GROUPING_ID(a, b)» ali «GROUPING(a)ANDGROUPING(b)» za hitro osveževanje materializiranega pogleda.
GROUPBY ne sme povzročiti podvojenih skupin. Na primer, "GROUP BY a, ROLLUP(a, b)" ni mogoče hitro osvežiti, ker povzroči podvojene skupine "(a), (a, b), AND (a)".
5.3.8.7 Omejitve hitrega osveževanja materializiranih pogledov z UNION ALL
Materializirani pogledi z UNIONALL nastavite operatersko podporo REFRESHFAST možnost, če so izpolnjeni naslednji pogoji:
Definirajoča poizvedba mora imeti UNIONALL operater na najvišji ravni.
O UNIONALL operatorja ni mogoče vdelati v podpoizvedbo, z eno izjemo: The UNIONALL je lahko v podpoizvedbi v FROM klavzula pod pogojem, da je definirajoča poizvedba v obliki SELECT * FROM (ogled ali podpoizvedba z UNIONALL), kot v naslednjem primeru:
CREATE VIEW view_with_unionall AS (IZBERI c.rowid crid, c.cust_id, 2 umarker FROM strank c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM strank c WHERE c.cust_last_name = 'Jones'); USTVARI MATERIALIZIRAN POGLED unionall_inside_view_mv HITRO OSVEŽI NA ZAHTEVO KOT IZBERI * IZ view_with_unionall;
Upoštevajte, da pogled view_with_unionall izpolnjuje zahteve po hitrem osveževanju.
Vsak blok poizvedbe v UNIONALL poizvedba mora izpolnjevati zahteve materializiranega pogleda s hitrim osveževanjem z agregati ali materializiranega pogleda s hitrim osveževanjem z združitvami.
Na tabelah je treba ustvariti ustrezne dnevnike materializiranih pogledov, kot je zahtevano za ustrezno vrsto materializiranega pogleda s hitrim osveževanjem.
Upoštevajte, da zbirka podatkov Oracle dovoljuje tudi poseben primer materializiranega pogleda ene tabele s spoji samo pod pogojem ROWID stolpec je bil vključen v SELECT seznamu in v dnevniku materializiranega pogleda. To je prikazano v definicijski poizvedbi pogleda view_with_unionall.
O SELECT seznam vsake poizvedbe mora vsebovati a UNIONALL marker in UNIONALL stolpec mora imeti v vsakem ločeno konstantno številsko ali nizovno vrednost UNIONALL podružnica. Poleg tega se mora stolpec z označevalci pojaviti na istem ordinalnem mestu v SELECT seznam vsakega bloka poizvedbe. glej "Označevalnik UNION ALL in prepis poizvedbe» za več informacij o UNIONALL označevalci.
Nekatere funkcije, kot so zunanja združevanja, poizvedbe zbranih materializiranih pogledov samo za vstavljanje in oddaljene tabele, niso podprte za materializirane poglede z UNIONALL. Upoštevajte pa, da je mogoče materializirane poglede, uporabljene pri podvajanju, ki ne vsebujejo združevanj ali agregatov, hitro osvežiti, ko UNIONALL ali se uporabljajo oddaljene tabele.
Inicializacijski parameter združljivosti mora biti nastavljen na 9.2.0 ali višje, da ustvarite materializirani pogled s hitrim osveževanjem z UNIONALL.
Nočem užaliti oboževalcev Oracla, a sodeč po njihovem seznamu omejitev se zdi, da ta mehanizem ni bil napisan v splošnem primeru z uporabo nekakšnega modela, temveč na tisoče Indijcev, kjer je vsak dobil možnost, da napisati svojo vejo in vsak od njih je naredil, kar je lahko. in naredil. Uporaba tega mehanizma za pravo logiko je kot hoja skozi minsko polje. Rudnik lahko dobite kadar koli, tako da pritisnete eno od neočitnih omejitev. Kako deluje, je prav tako ločeno vprašanje, vendar presega obseg tega članka.
Microsoft SQL Server
Dodatne zahteve
Poleg možnosti SET in zahtev za deterministične funkcije morajo biti izpolnjene naslednje zahteve:
Uporabnik, ki izvaja CREATE INDEX mora biti lastnik pogleda.
Ko ustvarite indeks, se IGNORE_DUP_KEY možnost mora biti nastavljena na OFF (privzeta nastavitev).
Tabele se morajo sklicevati z dvodelnimi imeni, shema.ime tabele v definiciji pogleda.
Uporabniško definirane funkcije, navedene v pogledu, morajo biti ustvarjene z uporabo WITH SCHEMABINDING možnost.
Vse uporabniško definirane funkcije, navedene v pogledu, se morajo sklicevati z dvodelnimi imeni, ..
Lastnost dostopa do podatkov uporabniško definirane funkcije mora biti NO SQL, lastnost zunanjega dostopa pa mora biti NO.
Funkcije izvajalnega okolja skupnega jezika (CLR) so lahko prikazane na izbirnem seznamu pogleda, vendar ne morejo biti del definicije ključa indeksa v gručah. Funkcije CLR se ne morejo pojaviti v členu WHERE pogleda ali členu ON operacije JOIN v pogledu.
Funkcije CLR in metode uporabniško definiranih tipov CLR, ki se uporabljajo v definiciji pogleda, morajo imeti nastavljene lastnosti, kot je prikazano v naslednji tabeli.
Nepremičnine
Opombe
DETERMINISTIČNO = PRAV
Mora biti izrecno deklariran kot atribut metode Microsoft .NET Framework.
NATANČNO = PRAV
Mora biti izrecno deklariran kot atribut metode .NET Framework.
DOSTOP DO PODATKOV = NI SQL
Določeno z nastavitvijo atributa DataAccess na DataAccessKind.None in atributa SystemDataAccess na SystemDataAccessKind.None.
ZUNANJI DOSTOP = ŠT
Ta lastnost je privzeto nastavljena na NO za rutine CLR.
Pogled je treba ustvariti z uporabo WITH SCHEMABINDING možnost.
Pogled se mora sklicevati samo na osnovne tabele, ki so v isti bazi podatkov kot pogled. Pogled se ne more sklicevati na druge poglede.
Stavek SELECT v definiciji pogleda ne sme vsebovati naslednjih elementov Transact-SQL:
COUNT
Funkcije ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSETIN OPENXML) OUTER pridruži se (LEFT, RIGHTali FULL)
Izpeljana tabela (definirana s podajanjem a SELECT izjava v FROM klavzula)
Samopridruževanje
Določanje stolpcev z uporabo SELECT * or SELECT <table_name>.*
DISTINCT STDEV, STDEVP, VAR, VARPali AVG
Izraz skupne tabele (CTE)
float1, besedilo, ntext, slika, XMLali datotečni tok stolpci
Podpoizvedba OVER klavzula, ki vključuje funkcije razvrščanja ali združevanja oken
Predikati celotnega besedila (CONTAINS, FREETEXT) SUM funkcijo, ki se sklicuje na ničelni izraz ORDER BY
Uporabniško definirana agregatna funkcija CLR TOP CUBE, ROLLUPali GROUPING SETS operaterji
MIN, MAX UNION, EXCEPTali INTERSECT operaterji TABLESAMPLE
Spremenljivke tabele OUTER APPLY or CROSS APPLY PIVOT, UNPIVOT
Redki nizi stolpcev
Funkcije v vrstici (TVF) ali funkcije z vrednostjo tabele z več stavki (MSTVF) OFFSET
CHECKSUM_AGG
1 Indeksirani pogled lahko vsebuje float stolpci; vendar takšnih stolpcev ni mogoče vključiti v ključ indeksa v gručah.
If GROUP BY je prisoten, mora vsebovati definicija VIEW COUNT_BIG(*) in ne sme vsebovati HAVING. Ti GROUP BY omejitve veljajo samo za definicijo indeksiranega pogleda. Poizvedba lahko v svojem načrtu izvajanja uporablja indeksirani pogled, tudi če ne izpolnjuje teh GROUP BY omejitve.
Če definicija pogleda vsebuje a GROUP BY se lahko ključ edinstvenega gručastega indeksa sklicuje samo na stolpce, določene v GROUP BY klavzula.
Tukaj je jasno, da Indijci niso bili vpleteni, saj so se odločili za to po shemi "naredili bomo malo, a dobro." To pomeni, da imajo več min na terenu, vendar je njihova lokacija bolj pregledna. Najbolj razočaranje je ta omejitev:
Pogled se mora sklicevati samo na osnovne tabele, ki so v isti bazi podatkov kot pogled. Pogled se ne more sklicevati na druge poglede.
V naši terminologiji to pomeni, da funkcija ne more dostopati do druge materializirane funkcije. To v kali poseka vso ideologijo.
Tudi ta omejitev (in nadaljevanje v besedilu) močno zmanjša primere uporabe:
Stavek SELECT v definiciji pogleda ne sme vsebovati naslednjih elementov Transact-SQL:
COUNT
Funkcije ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSETIN OPENXML) OUTER pridruži se (LEFT, RIGHTali FULL)
Izpeljana tabela (definirana s podajanjem a SELECT izjava v FROM klavzula)
Samopridruževanje
Določanje stolpcev z uporabo SELECT * or SELECT <table_name>.*
DISTINCT STDEV, STDEVP, VAR, VARPali AVG
Izraz skupne tabele (CTE)
float1, besedilo, ntext, slika, XMLali datotečni tok stolpci
Podpoizvedba OVER klavzula, ki vključuje funkcije razvrščanja ali združevanja oken
Predikati celotnega besedila (CONTAINS, FREETEXT) SUM funkcijo, ki se sklicuje na ničelni izraz ORDER BY
Uporabniško definirana agregatna funkcija CLR TOP CUBE, ROLLUPali GROUPING SETS operaterji
MIN, MAX UNION, EXCEPTali INTERSECT operaterji TABLESAMPLE
Spremenljivke tabele OUTER APPLY or CROSS APPLY PIVOT, UNPIVOT
Redki nizi stolpcev
Funkcije v vrstici (TVF) ali funkcije z vrednostjo tabele z več stavki (MSTVF) OFFSET
CHECKSUM_AGG
OUTER JOINS, UNION, ORDER BY in drugi so prepovedani. Morda bi bilo lažje določiti, kaj se lahko uporabi, namesto česa se ne sme uporabiti. Seznam bi bil verjetno precej krajši.
Če povzamem: ogromen nabor omejitev v vsakem (naj upoštevamo komercialnem) DBMS proti nobeni (z izjemo ene logične, ne tehnične) v tehnologiji LGPL. Vendar je treba opozoriti, da je implementacija tega mehanizma v relacijsko logiko nekoliko težja kot v opisani funkcionalni logiki.
Реализация
Kako deluje? PostgreSQL se uporablja kot "virtualni stroj". V notranjosti je zapleten algoritem, ki gradi poizvedbe. Tukaj vir. In ne obstaja samo velik nabor hevristik s kupom če-jev. Torej, če imate nekaj mesecev časa za študij, lahko poskusite razumeti arhitekturo.
Ali deluje učinkovito? Zelo učinkovito. Na žalost je to težko dokazati. Lahko samo rečem, da če upoštevate na tisoče poizvedb, ki obstajajo v velikih aplikacijah, potem so v povprečju učinkovitejše od tistih dobrega razvijalca. Odličen programer SQL lahko učinkoviteje napiše katero koli poizvedbo, a s tisoč poizvedbami preprosto ne bo imel motivacije ali časa za to. Edina stvar, ki jo lahko zdaj navedem kot dokaz učinkovitosti, je, da več projektov deluje na platformi, zgrajeni na tej DBMS ERP sistemi, ki imajo na tisoče različnih MATERIALIZIRANIH funkcij, s tisoči uporabnikov in terabajtnimi bazami podatkov s stotinami milijonov zapisov, ki tečejo na navadnem dvoprocesorskem strežniku. Učinkovitost pa lahko vsak preveri/ovrže s prenosom platforma in PostgreSQL, vključen beleženje poizvedb SQL in poskušanje tam spremeniti logiko in podatke.
V naslednjih člankih bom govoril tudi o tem, kako lahko nastavite omejitve funkcij, delate s sejami sprememb in še veliko več.