Usklađivanje pisanja i čitanja u bazi podataka

Usklađivanje pisanja i čitanja u bazi podataka
U prethodnom članak Opisao sam koncept i implementaciju baze podataka izgrađene na temelju funkcija, a ne tablica i polja kao u relacijskim bazama podataka. Navedeno je mnogo primjera koji pokazuju prednosti ovog pristupa u odnosu na klasični. Mnogi su ih smatrali nedovoljno uvjerljivima.

U ovom ću članku pokazati kako vam ovaj koncept omogućuje brzo i praktično balansiranje pisanja i čitanja u bazi podataka bez ikakve promjene u operativnoj logici. Slična se funkcionalnost pokušala implementirati u moderne komercijalne DBMS-ove (osobito Oracle i Microsoft SQL Server). Na kraju članka pokazat ću da ono što su napravili, najblaže rečeno, nije baš dobro ispalo.

Opis

Kao i prije, radi boljeg razumijevanja opis ću započeti primjerima. Recimo da trebamo implementirati logiku koja će vratiti popis odjela s brojem zaposlenih u njima i njihovom ukupnom plaćom.

U funkcionalnoj bazi podataka to bi izgledalo ovako:

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;

SELECT name(Department d), countEmployees(d), salarySum(d);

Složenost izvršavanja ovog upita u bilo kojem DBMS-u bit će jednaka O(broj zaposlenih)jer ovaj izračun zahtijeva skeniranje cijele tablice zaposlenika i njihovo grupiranje po odjelima. Bit će i neki mali (vjerujemo da ima puno više zaposlenika nego odjela) dodatak ovisno o odabranom planu O(log broj zaposlenih) ili O(broj odjela) za grupiranje i tako dalje.

Jasno je da opterećenje izvršenja može biti različito u različitim DBMS-ovima, ali složenost se neće ni na koji način promijeniti.

U predloženoj implementaciji, funkcionalni DBMS će generirati jedan podupit koji će izračunati potrebne vrijednosti za odjel, a zatim napraviti JOIN s tablicom odjela kako bi se dobio naziv. Međutim, za svaku funkciju, prilikom deklaracije, moguće je postaviti posebnu oznaku MATERIALIZED. Sustav će automatski stvoriti odgovarajuće polje za svaku takvu funkciju. Prilikom promjene vrijednosti funkcije, vrijednost polja također će se promijeniti u istoj transakciji. Prilikom pristupa ovoj funkciji, pristupit će se unaprijed izračunatom polju.

Konkretno, ako postavite MATERIALIZED za funkcije countZaposlenici и plaćaSum, tada će se tablici s popisom odjela dodati dva polja u koja će biti pohranjen broj zaposlenika i njihova ukupna plaća. Kad god dođe do promjene zaposlenika, njihovih plaća ili pripadnosti odjelima, sustav će automatski promijeniti vrijednosti ovih polja. Gornji upit će izravno pristupiti ovim poljima i bit će izvršen u njima O(broj odjela).

Koja su ograničenja? Samo jedna stvar: takva funkcija mora imati konačan broj ulaznih vrijednosti za koje je definirana njezina vrijednost. U suprotnom, bit će nemoguće izgraditi tablicu koja pohranjuje sve svoje vrijednosti, jer ne može postojati tablica s beskonačnim brojem redaka.

Primjer:

employeesCount ‘Количество сотрудников с зарплатой > N’ (Department d, NUMERIC[10,2] N) = 
    GROUP SUM salary(Employee e) IF department(e) = d AND salary(e) > N;

Ova je funkcija definirana za beskonačan broj vrijednosti N (na primjer, svaka negativna vrijednost je prikladna). Stoga na njega ne možete staviti MATERIJALIZIRANO. Dakle, ovo je logično ograničenje, a ne tehničko (to jest, ne zato što ga nismo mogli implementirati). Inače, nema ograničenja. Možete koristiti grupiranje, sortiranje, I i ILI, PARTICIJU, rekurziju itd.

Na primjer, u problemu 2.2 prethodnog članka, možete staviti MATERIALIZED na obje funkcije:

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;

Sustav će sam kreirati jednu tablicu s tipskim ključevima Kupac, Proizvod и CIJELI, dodati će mu dva polja i ažurirati vrijednosti polja u njima sa svim promjenama. Kada se naprave daljnji pozivi ovim funkcijama, one se neće izračunati, već će se vrijednosti očitati iz odgovarajućih polja.

Pomoću ovog mehanizma možete se, primjerice, riješiti rekurzija (CTE) u upitima. Konkretno, razmotrite grupe koje tvore stablo koristeći odnos dijete/roditelj (svaka grupa ima vezu na svog roditelja):

parent = DATA Group (Group);

U funkcionalnoj bazi podataka, logika rekurzije može se specificirati na sljedeći 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;

Pošto za funkciju jeRoditelj ima oznaku MATERIALIZIRAN, tada će se za njega kreirati tablica s dva ključa (grupe) u kojoj je polje jeRoditelj bit će istina samo ako je prvi ključ dijete drugog. Broj unosa u ovoj tablici bit će jednak broju grupa pomnoženom s prosječnom dubinom stabla. Ako trebate, na primjer, izbrojati broj potomaka određene skupine, možete koristiti ovu funkciju:

childrenCount (Group g) = GROUP SUM 1 IF isParent(Group child, g);

U SQL upitu neće biti CTE-a. Umjesto toga bit će jednostavno GROUP BY.

Pomoću ovog mehanizma također možete jednostavno denormalizirati bazu podataka ako je potrebno:

CLASS Order 'Заказ';
date 'Дата' = DATA DATE (Order);

CLASS OrderDetail 'Строка заказа';
order 'Заказ' = DATA Order (OrderDetail);
date 'Дата' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;

Prilikom poziva funkcije podaci za redak naloga, polje za koje postoji indeks bit će pročitano iz tablice s redovima naloga. Kada se datum narudžbe promijeni, sustav će sam automatski ponovno izračunati denormalizirani datum u retku.

Prednosti

Čemu služi cijeli ovaj mehanizam? U klasičnim DBMS-ovima, bez ponovnog pisanja upita, programer ili DBA mogu samo promijeniti indekse, odrediti statistiku i reći planeru upita kako da ih izvrši (a HINT-ovi su dostupni samo u komercijalnim DBMS-ovima). Koliko god se trudili, neće uspjeti ispuniti prvi upit u članku u O (broj odjela) bez mijenjanja upita ili dodavanja okidača. U predloženoj shemi, u fazi razvoja ne morate razmišljati o strukturi pohrane podataka i koje agregacije koristiti. Sve se to može jednostavno promijeniti u hodu, izravno u radu.

U praksi to izgleda ovako. Neki ljudi razvijaju logiku izravno na temelju zadatka. Ne razumiju algoritme i njihovu složenost, niti izvedbene planove, niti vrste spojeva, niti bilo koju drugu tehničku komponentu. Ovi ljudi su više poslovni analitičari nego programeri. Zatim sve to ide u testiranje ili rad. Omogućuje bilježenje dugotrajnih upita. Kada se otkrije dugačak upit, drugi ljudi (više tehnički - u biti DBA) odlučuju omogućiti MATERIALIZED na nekoj srednjoj funkciji. To malo usporava snimanje (budući da zahtijeva ažuriranje dodatnog polja u transakciji). No, nije samo ovaj upit značajno ubrzan, već i svi drugi koji koriste ovu funkciju. U isto vrijeme relativno je lako odlučiti koju funkciju materijalizirati. Dva glavna parametra: broj mogućih ulaznih vrijednosti (ovo je koliko će zapisa biti u odgovarajućoj tablici) i koliko se često koristi u drugim funkcijama.

analoga

Moderni komercijalni DBMS-ovi imaju slične mehanizme: MATERIALIZED VIEW s BRZIM OSVJEŽAVANJEM (Oracle) i INDEXED VIEW (Microsoft SQL Server). U PostgreSQL-u, MATERIALIZED VIEW se ne može ažurirati u transakciji, već samo na zahtjev (pa čak i uz vrlo stroga ograničenja), tako da ga ne uzimamo u obzir. Ali oni imaju nekoliko problema koji značajno ograničavaju njihovu upotrebu.

Kao prvo, materijalizaciju možete omogućiti samo ako ste već stvorili obični VIEW. U protivnom ćete morati ponovno napisati preostale zahtjeve za pristup novostvorenom pogledu da biste koristili ovu materijalizaciju. Ili ostavite sve kako jest, ali će biti barem neučinkovito ako postoje određeni već unaprijed izračunati podaci, ali mnogi upiti ih ne koriste uvijek, već ih ponovno izračunavaju.

Drugo, imaju ogroman broj ograničenja:

Proročanstvo

5.3.8.4 Opća ograničenja za brzo osvježavanje

Definirajući upit materijaliziranog pogleda ograničen je na sljedeći način:

  • Materijalizirani pogled ne smije sadržavati reference na izraze koji se ne ponavljaju kao što je SYSDATE i ROWNUM.
  • Materijalizirani prikaz ne smije sadržavati reference na RAW or LONG RAW vrste podataka.
  • Ne može sadržavati a SELECT popis podupita.
  • Ne može sadržavati analitičke funkcije (npr. RANK) u SELECT klauzula.
  • Ne može referencirati tablicu na kojoj je XMLIndex indeks je definiran.
  • Ne može sadržavati a MODEL klauzula.
  • Ne može sadržavati a HAVING klauzula s podupitom.
  • Ne može sadržavati ugniježđene upite koji imaju ANY, ALL, ili NOT EXISTS.
  • Ne može sadržavati a [START WITH …] CONNECT BY klauzula.
  • Ne može sadržavati više tablica s detaljima na različitim mjestima.
  • ON COMMIT materijalizirani prikazi ne mogu imati udaljene tablice detalja.
  • Ugniježđeni materijalizirani pogledi moraju imati spoj ili agregat.
  • Materijalizirani spojeni pogledi i materijalizirani skupni pogledi s a GROUP BY klauzula ne može odabrati iz indeksno organizirane tablice.

5.3.8.5 Ograničenja brzog osvježavanja na materijaliziranim prikazima samo sa spojevima

Definiranje upita za materijalizirane prikaze samo sa spojevima i bez agregata ima sljedeća ograničenja brzog osvježavanja:

  • Sva ograničenja iz «Opća ograničenja za brzo osvježavanje”.
  • Ne mogu imati GROUP BY klauze ili agregati.
  • Redovi svih tablica u FROM popis se mora pojaviti u SELECT popis upita.
  • Dnevnici materijaliziranog pogleda moraju postojati s redovima za sve osnovne tablice u FROM popis upita.
  • Ne možete stvoriti materijalizirani prikaz koji se može brzo osvježiti iz više tablica s jednostavnim spojevima koji uključuju stupac vrste objekta u SELECT izjava.

Također, metoda osvježavanja koju odaberete neće biti optimalno učinkovita ako:

  • Definirajući upit koristi vanjsko spajanje koje se ponaša kao unutarnje spajanje. Ako definirajući upit sadrži takvo spajanje, razmislite o ponovnom pisanju definirajućeg upita tako da sadrži unutarnje spajanje.
  • Korištenje električnih romobila ističe SELECT popis materijaliziranog pogleda sadrži izraze na stupcima iz više tablica.

5.3.8.6 Ograničenja brzog osvježavanja na materijaliziranim pogledima s agregatima

Definiranje upita za materijalizirane prikaze s agregatima ili spojevima ima sljedeća ograničenja brzog osvježavanja:

Brzo osvježavanje podržano je za oba ON COMMIT i ON DEMAND materijalizirani prikazi, no vrijede sljedeća ograničenja:

  • Sve tablice u materijaliziranom pogledu moraju imati zapisnike materijaliziranog pogleda, a zapisnici materijaliziranog pogleda moraju:
    • Sadrži sve stupce iz tablice na koju se upućuje u materijaliziranom prikazu.
    • Navedite s ROWID i INCLUDING NEW VALUES.
    • Navedite SEQUENCE ako se od tablice očekuje kombinacija umetanja/izravnih učitavanja, brisanja i ažuriranja.

  • Samo SUM, COUNT, AVG, STDDEV, VARIANCE, MIN i MAX podržani su za brzo osvježavanje.
  • COUNT(*) mora biti navedeno.
  • Zbirne funkcije moraju se pojaviti samo kao krajnji vanjski dio izraza. Odnosno, agregati kao npr AVG(AVG(x)) or AVG(x)+ AVG(x) Nisu dopusteni.
  • Za svaki agregat kao npr AVG(expr), odgovarajući COUNT(expr) mora biti prisutan. Oracle to preporučuje SUM(expr) biti naveden.
  • If VARIANCE(expr) or STDDEV(expr) je navedeno, COUNT(expr) i SUM(expr) mora biti navedeno. Oracle to preporučuje SUM(expr *expr) biti naveden.
  • Korištenje električnih romobila ističe SELECT stupac u definirajućem upitu ne može biti složen izraz sa stupcima iz više osnovnih tablica. Moguće rješenje za ovo je korištenje ugniježđenog materijaliziranog pogleda.
  • Korištenje električnih romobila ističe SELECT popis mora sadržavati sve GROUP BY stupovi.
  • Materijalizirani pogled ne temelji se na jednoj ili više udaljenih tablica.
  • Ako koristite a CHAR tipa podataka u stupcima filtera dnevnika materijaliziranog pogleda, skupovi znakova glavnog mjesta i materijaliziranog pogleda moraju biti isti.
  • Ako materijalizirani pogled ima jedno od sljedećeg, tada je brzo osvježavanje podržano samo na konvencionalnim DML umetcima i izravnim učitavanjima.
    • Materijalizirani pogledi sa MIN or MAX agregati
    • Materijalizirani pogledi koji imaju SUM(expr) ali ne COUNT(expr)
    • Materijalizirani pogledi bez COUNT(*)

    Takav materijalizirani pogled naziva se materijalizirani pogled samo za umetanje.

  • Materijalizirani pogled sa MAX or MIN može se brzo osvježiti nakon brisanja ili miješanih DML izjava ako nema WHERE klauzula.
    Max/min brzo osvježavanje nakon brisanja ili miješanog DML-a nema isto ponašanje kao slučaj samo za umetanje. Briše i ponovno izračunava maksimalne/minimalne vrijednosti za zahvaćene skupine. Morate biti svjesni njegovog utjecaja na izvedbu.
  • Materijalizirani pogledi s imenovanim pogledima ili podupitima u FROM klauzula se može brzo osvježiti pod uvjetom da se pogledi mogu potpuno spojiti. Za informacije o tome koji će se prikazi spojiti, pogledajte Referenca jezika Oracle Database SQL.
  • Ako nema vanjskih spajanja, možete imati proizvoljne odabire i spajanja u WHERE klauzula.
  • Materijalizirani agregatni prikazi s vanjskim spojevima mogu se brzo osvježiti nakon konvencionalnog DML-a i izravnih učitavanja, pod uvjetom da je samo vanjska tablica izmijenjena. Također, moraju postojati jedinstvena ograničenja na spojnim stupcima unutarnje spojene tablice. Ako postoje vanjski spojevi, svi spojevi moraju biti povezani putem ANDs i mora koristiti jednakost (=) operator.
  • Za materijalizirane poglede sa CUBE, ROLLUP, grupiranje skupova ili njihovo ulančavanje, primjenjuju se sljedeća ograničenja:
    • Korištenje električnih romobila ističe SELECT popis treba sadržavati razlikovanje grupiranja koje može biti a GROUPING_ID funkcionirati na svim GROUP BY izrazi ili GROUPING funkcije po jedan za svakoga GROUP BY izraz. Na primjer, ako je GROUP BY klauzula materijaliziranog pogleda je "GROUP BY CUBE(a, b)", onda SELECT popis treba sadržavati ili "GROUPING_ID(a, b)" ili "GROUPING(a) AND GROUPING(b)» kako bi se materijalizirani pogled mogao brzo osvježiti.
    • GROUP BY ne bi trebalo rezultirati dvostrukim grupiranjem. Na primjer, "GROUP BY a, ROLLUP(a, b)" nije moguće brzo osvježiti jer rezultira dvostrukim grupiranjem "(a), (a, b), AND (a)”.

5.3.8.7 Ograničenja brzog osvježavanja materijaliziranih pogleda s UNION ALL

Materijalizirani pogledi s UNION ALL set operator support the REFRESH FAST opciju ako su zadovoljeni sljedeći uvjeti:

  • Definirajući upit mora imati UNION ALL operater na najvišoj razini.

    Korištenje električnih romobila ističe UNION ALL operator ne može biti ugrađen unutar podupita, uz jednu iznimku: The UNION ALL može biti u podupitu u FROM klauzula pod uvjetom da je definirajući upit oblika SELECT * FROM (pogledajte ili podupitajte s UNION ALL) kao u sljedećem primjeru:

    CREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM kupaca c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM kupaca c WHERE c.cust_last_name = 'Jones'); STVARAJ MATERIJALIZIRANI PRIKAZ unionall_inside_view_mv BRZO OSVJEŽI NA ZAHTJEV KAO ODABIR * IZ view_with_unionall;
    

    Imajte na umu da pogled view_with_unionall zadovoljava zahtjeve za brzim osvježavanjem.

  • Svaki blok upita u UNION ALL upit mora zadovoljiti zahtjeve brzog osvježavajućeg materijaliziranog pogleda s agregatima ili brzo osvježavajućeg materijaliziranog pogleda sa spojevima.

    Odgovarajući dnevnici materijaliziranog pogleda moraju se kreirati na tablicama prema potrebi za odgovarajući tip materijaliziranog pogleda koji se brzo osvježava.
    Imajte na umu da Oracle Database također dopušta poseban slučaj materijaliziranog pogleda jedne tablice sa spojevima samo uz uvjet ROWID stupac je uključen u SELECT popisu iu dnevniku materijaliziranog pogleda. Ovo je prikazano u definirajućem upitu pogleda view_with_unionall.

  • Korištenje električnih romobila ističe SELECT popis svakog upita mora sadržavati a UNION ALL marker i UNION ALL stupac mora imati različitu konstantnu brojčanu vrijednost ili vrijednost niza u svakom UNION ALL podružnica. Nadalje, stupac oznake mora se pojaviti na istom rednom mjestu u SELECT popis svakog bloka upita. vidi "Oznaka UNION ALL i prepisivanje upita» za više informacija o UNION ALL markera.
  • Neke značajke kao što su vanjska spajanja, upiti skupnih materijaliziranih pogleda samo za umetanje i udaljene tablice nisu podržane za materijalizirane poglede s UNION ALL. Imajte na umu, međutim, da se materijalizirani pogledi korišteni u replikaciji, koji ne sadrže spojeve ili agregate, mogu brzo osvježiti kada UNION ALL ili se koriste udaljene tablice.
  • Parametar inicijalizacije kompatibilnosti mora biti postavljen na 9.2.0 ili višu za stvaranje materijaliziranog prikaza koji se može brzo osvježavati s UNION ALL.

Ne želim uvrijediti obožavatelje Oraclea, ali sudeći po njihovom popisu ograničenja, čini se da ovaj mehanizam nije napisan u općem slučaju, koristeći nekakav model, već tisuće Indijaca, gdje je svatko dobio priliku napisati svoju vlastitu granu, i svaki od njih je učinio što je mogao i učinio. Korištenje ovog mehanizma za pravu logiku je poput hodanja kroz minsko polje. Rudnik možete dobiti u bilo kojem trenutku pritiskom na jedno od neočitih ograničenja. Kako to funkcionira također je zasebno pitanje, ali je izvan okvira ovog članka.

Microsoft SQL Server

Dodatni zahtjevi

Uz SET opcije i zahtjeve determinističke funkcije, moraju biti ispunjeni sljedeći zahtjevi:

  • Korisnik koji izvršava CREATE INDEX mora biti vlasnik pogleda.
  • Kada kreirate indeks, IGNORE_DUP_KEY opcija mora biti postavljena na ISKLJUČENO (zadana postavka).
  • Tablice moraju biti navedene dvodijelnim nazivima, shema.naziv tablice u definiciji prikaza.
  • Korisnički definirane funkcije navedene u prikazu moraju se stvoriti korištenjem WITH SCHEMABINDING opcija.
  • Sve korisnički definirane funkcije navedene u prikazu moraju biti navedene dvodijelnim imenima, ..
  • Svojstvo pristupa podacima korisnički definirane funkcije mora biti NO SQL, a svojstvo vanjskog pristupa mora biti NO.
  • Funkcije vremena izvođenja zajedničkog jezika (CLR) mogu se pojaviti na popisu odabira pogleda, ali ne mogu biti dio definicije ključa klasteriranog indeksa. CLR funkcije se ne mogu pojaviti u klauzuli WHERE pogleda ili klauzuli ON operacije JOIN u pogledu.
  • CLR funkcije i metode CLR korisnički definiranih tipova koji se koriste u definiciji pogleda moraju imati postavljena svojstva kao što je prikazano u sljedećoj tablici.

    Svojstvo
    bilješke

    DETERMINISTIČNO = ISTINITO
    Mora se izričito deklarirati kao atribut metode Microsoft .NET Framework.

    PRECIZNO = ISTINITO
    Mora se izričito deklarirati kao atribut metode .NET Framework.

    PRISTUP PODACIMA = NEMA SQL-a
    Određuje se postavljanjem atributa DataAccess na DataAccessKind.None i atributa SystemDataAccess na SystemDataAccessKind.None.

    VANJSKI PRISTUP = NE
    Zadana vrijednost ovog svojstva je NE za CLR rutine.

  • Pogled se mora stvoriti korištenjem WITH SCHEMABINDING opcija.
  • Pogled mora referencirati samo osnovne tablice koje su u istoj bazi podataka kao i pogled. Pogled ne može upućivati ​​na druge prikaze.
  • Izjava SELECT u definiciji prikaza ne smije sadržavati sljedeće Transact-SQL elemente:

    COUNT
    ROWSET funkcije (OPENDATASOURCE, OPENQUERY, OPENROWSET, I OPENXML)
    OUTER pridružuje se (LEFT, RIGHT, ili FULL)

    Izvedena tablica (definirana navođenjem a SELECT izjava u FROM klauzula)
    Samospoji
    Određivanje stupaca pomoću SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, ili AVG
    Uobičajeni tablični izraz (CTE)

    plutati1, tekst, ntext, slika, XML, ili tok datoteka stupovi
    poduprt
    OVER klauzula, koja uključuje funkcije rangiranja ili skupnog prozora

    Predikati punog teksta (CONTAINS, FREETEXT)
    SUM funkcija koja referira na nulti izraz
    ORDER BY

    CLR korisnički definirana agregatna funkcija
    TOP
    CUBE, ROLLUP, ili GROUPING SETS Operatori

    MIN, MAX
    UNION, EXCEPT, ili INTERSECT Operatori
    TABLESAMPLE

    Tablične varijable
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Rijetki skupovi stupaca
    Inline (TVF) ili funkcije s tabličnim vrijednostima s više naredbi (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Indeksirani prikaz može sadržavati plutati stupci; međutim, takvi stupci ne mogu biti uključeni u klasterirani ključ indeksa.

  • If GROUP BY postoji, definicija VIEW mora sadržavati COUNT_BIG(*) i ne smije sadržavati HAVING, To GROUP BY ograničenja su primjenjiva samo na definiciju indeksiranog prikaza. Upit može koristiti indeksirani prikaz u svom planu izvršenja čak i ako ne zadovoljava ove GROUP BY ograničenja.
  • Ako definicija pogleda sadrži a GROUP BY klauzula, ključ jedinstvenog grupiranog indeksa može referencirati samo stupce navedene u GROUP BY klauzula.

Ovdje je jasno da Indijci nisu bili umiješani, jer su to odlučili učiniti po shemi "radit ćemo malo, ali dobro". Odnosno, imaju više mina na terenu, ali je njihova lokacija transparentnija. Ono što najviše razočarava je ovo ograničenje:

Pogled mora referencirati samo osnovne tablice koje su u istoj bazi podataka kao i pogled. Pogled ne može upućivati ​​na druge prikaze.

U našoj terminologiji to znači da funkcija ne može pristupiti drugoj materijaliziranoj funkciji. Time se u korijenu ruši svaka ideologija.
Također, ovo ograničenje (i dalje u tekstu) uvelike smanjuje slučajeve upotrebe:

Izjava SELECT u definiciji prikaza ne smije sadržavati sljedeće Transact-SQL elemente:

COUNT
ROWSET funkcije (OPENDATASOURCE, OPENQUERY, OPENROWSET, I OPENXML)
OUTER pridružuje se (LEFT, RIGHT, ili FULL)

Izvedena tablica (definirana navođenjem a SELECT izjava u FROM klauzula)
Samospoji
Određivanje stupaca pomoću SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARP, ili AVG
Uobičajeni tablični izraz (CTE)

plutati1, tekst, ntext, slika, XML, ili tok datoteka stupovi
poduprt
OVER klauzula, koja uključuje funkcije rangiranja ili skupnog prozora

Predikati punog teksta (CONTAINS, FREETEXT)
SUM funkcija koja referira na nulti izraz
ORDER BY

CLR korisnički definirana agregatna funkcija
TOP
CUBE, ROLLUP, ili GROUPING SETS Operatori

MIN, MAX
UNION, EXCEPT, ili INTERSECT Operatori
TABLESAMPLE

Tablične varijable
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Rijetki skupovi stupaca
Inline (TVF) ili funkcije s tabličnim vrijednostima s više naredbi (MSTVF)
OFFSET

CHECKSUM_AGG

VANJSKI SPOJOVI, UNION, ORDER BY i drugi su zabranjeni. Možda je bilo lakše odrediti što se može koristiti nego što se ne može koristiti. Popis bi vjerojatno bio puno kraći.

Ukratko: ogroman skup ograničenja u svakom (napomenimo komercijalnom) DBMS-u naspram nijednog (s izuzetkom jednog logičkog, ne tehničkog) u LGPL tehnologiji. Međutim, treba napomenuti da je implementacija ovog mehanizma u relacijskoj logici nešto teža nego u opisanoj funkcionalnoj logici.

Provedba

Kako radi? PostgreSQL se koristi kao "virtualni stroj". Unutra je složen algoritam koji gradi upite. Ovdje izvor. I ne postoji samo veliki skup heuristika s hrpom ako. Dakle, ako imate par mjeseci za učenje, možete pokušati razumjeti arhitekturu.

Djeluje li učinkovito? Prilično učinkovito. Nažalost, to je teško dokazati. Mogu samo reći da ako uzmete u obzir tisuće zahtjeva koji postoje u velikim aplikacijama, oni su u prosjeku učinkovitiji od onih dobrog programera. Izvrstan SQL programer može učinkovitije napisati bilo koji upit, ali s tisuću upita jednostavno neće imati motivacije ni vremena za to. Jedina stvar koju sada mogu navesti kao dokaz učinkovitosti je da nekoliko projekata radi na platformi izgrađenoj na ovom DBMS-u ERP sustavi, koji imaju tisuće različitih MATERIJALIZIRANIH funkcija, s tisućama korisnika i terabajtnim bazama podataka sa stotinama milijuna zapisa koji rade na običnom dvoprocesorskom poslužitelju. Međutim, svatko može provjeriti/opovrgnuti učinkovitost preuzimanjem platforma i PostgreSQL, Upaljeno zapisujući SQL upite i pokušavajući promijeniti logiku i podatke tamo.

U sljedećim člancima također ću govoriti o tome kako možete postaviti ograničenja funkcija, raditi sa sesijama promjena i još mnogo toga.

Izvor: www.habr.com

Dodajte komentar