Balansere skriver og leser i en database

Balansere skriver og leser i en database
I forrige artikkel Jeg beskrev konseptet og implementeringen av en database bygget på funksjoner, fremfor tabeller og felt som i relasjonsdatabaser. Den ga mange eksempler som viste fordelene med denne tilnærmingen fremfor den klassiske. Mange fant dem ikke overbevisende nok.

I denne artikkelen vil jeg vise hvordan dette konseptet lar deg raskt og enkelt balansere skriving og lesing til databasen uten endringer i driftslogikken. Lignende funksjonalitet har blitt forsøkt implementert i moderne kommersielle DBMS-er (spesielt Oracle og Microsoft SQL Server). På slutten av artikkelen skal jeg vise at det de gjorde, mildt sagt, ikke fungerte særlig bra.

beskrivelse

Som før vil jeg for bedre forståelse starte beskrivelsen med eksempler. La oss si at vi må implementere logikk som vil returnere en liste over avdelinger med antall ansatte i dem og deres totale lønn.

I en funksjonell database vil det se slik ut:

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);

Kompleksiteten ved å utføre denne spørringen i et hvilket som helst DBMS vil tilsvare O(antall ansatte)fordi denne beregningen krever at man skanner hele tabellen over ansatte og deretter grupperer dem etter avdeling. Det vil også komme noen små (vi tror det er mange flere ansatte enn avdelinger) tillegg avhengig av valgt plan O(logg antall ansatte) eller O(antall avdelinger) for gruppering og så videre.

Det er klart at utførelsesoverhead kan være forskjellig i forskjellige DBMS-er, men kompleksiteten vil ikke endre seg på noen måte.

I den foreslåtte implementeringen vil den funksjonelle DBMS generere en underspørring som vil beregne de nødvendige verdiene for avdelingen, og deretter lage en JOIN med avdelingstabellen for å få navnet. For hver funksjon er det imidlertid mulig å sette inn en spesiell MATERIALISERT markør ved deklarering. Systemet vil automatisk opprette et tilsvarende felt for hver slik funksjon. Når du endrer verdien på en funksjon, vil verdien av feltet også endres i samme transaksjon. Når du får tilgang til denne funksjonen, vil det forhåndsberegnete feltet bli åpnet.

Spesielt hvis du angir MATERIALISERT for funksjoner telle ansatte и lønnSum, så vil to felt bli lagt til i tabellen med avdelingslisten, som vil lagre antall ansatte og deres totale lønn. Når det er en endring i ansatte, deres lønn eller avdelingstilhørighet, vil systemet automatisk endre verdiene til disse feltene. Spørringen ovenfor vil få direkte tilgang til disse feltene og vil bli utført i O(antall avdelinger).

Hva er begrensningene? Bare én ting: en slik funksjon må ha et begrenset antall inngangsverdier som verdien er definert for. Ellers vil det være umulig å bygge en tabell som lagrer alle verdiene, siden det ikke kan være en tabell med et uendelig antall rader.

Eksempel:

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

Denne funksjonen er definert for et uendelig antall verdier av N (for eksempel er enhver negativ verdi egnet). Derfor kan du ikke sette MATERIALIZED på den. Så dette er en logisk begrensning, ikke en teknisk (det vil si ikke fordi vi ikke kunne implementere den). Ellers er det ingen begrensninger. Du kan bruke grupperinger, sortering, OG og ELLER, PARTISERING, rekursjon osv.

For eksempel, i oppgave 2.2 i forrige artikkel, kan du sette MATERIALIZED på begge funksjonene:

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;

Selve systemet vil lage én tabell med typetaster Kunde-, Produkt и INTEGER, vil legge til to felt til den og vil oppdatere feltverdiene i dem med eventuelle endringer. Når ytterligere anrop til disse funksjonene gjøres, vil de ikke bli beregnet, men verdiene vil i stedet leses fra de tilsvarende feltene.

Ved å bruke denne mekanismen kan du for eksempel bli kvitt rekursjoner (CTE) i spørringer. Tenk spesielt på grupper som danner et tre ved å bruke barnet/foreldre-forholdet (hver gruppe har en lenke til sin overordnede):

parent = DATA Group (Group);

I en funksjonell database kan rekursjonslogikk spesifiseres som følger:

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;

Siden for funksjonen er Foreldre er merket MATERIALISERT, vil det opprettes en tabell med to nøkler (grupper) for den, der feltet er Foreldre vil være sant bare hvis den første nøkkelen er et barn av den andre. Antall oppføringer i denne tabellen vil være lik antall grupper multiplisert med gjennomsnittlig dybde på treet. Hvis du for eksempel trenger å telle antall etterkommere av en bestemt gruppe, kan du bruke denne funksjonen:

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

Det vil ikke være noen CTE i SQL-spørringen. I stedet vil det være en enkel GROUP BY.

Ved å bruke denne mekanismen kan du også enkelt denormalisere databasen om nødvendig:

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

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

Når du kaller en funksjon data for ordrelinjen vil feltet som det er indeks for leses fra tabellen med ordrelinjer. Når bestillingsdatoen endres, vil systemet selv automatisk beregne den denormaliserte datoen i linjen på nytt.

Fordeler

Hva er hele denne mekanismen til for? I klassiske DBMS-er, uten å omskrive spørringer, kan en utvikler eller DBA bare endre indekser, bestemme statistikk og fortelle spørringsplanleggeren hvordan de skal utføres (og TIPS er kun tilgjengelig i kommersielle DBMS-er). Uansett hvor hardt de prøver, vil de ikke kunne fullføre den første spørringen i artikkelen i O (antall avdelinger) uten å endre søk eller legge til triggere. I den foreslåtte ordningen trenger du ikke på utviklingsstadiet å tenke på datalagringsstrukturen og hvilke aggregeringer du skal bruke. Alt dette kan enkelt endres i farten, direkte i drift.

I praksis ser det slik ut. Noen mennesker utvikler logikk direkte basert på oppgaven. De forstår ikke algoritmer og deres kompleksitet, heller ikke utførelsesplaner, eller typer sammenføyninger, eller noen annen teknisk komponent. Disse menneskene er mer forretningsanalytikere enn utviklere. Deretter går alt dette til testing eller drift. Aktiverer logging av langvarige spørringer. Når et langt søk oppdages, bestemmer andre personer (mer tekniske - egentlig DBA) seg for å aktivere MATERIALIZED på en mellomfunksjon. Dette bremser opptaket litt (siden det krever oppdatering av et ekstra felt i transaksjonen). Imidlertid er ikke bare denne spørringen betydelig raskere, men også alle andre som bruker denne funksjonen. Samtidig er det relativt enkelt å bestemme hvilken funksjon som skal materialiseres. To hovedparametere: antall mulige inngangsverdier (dette er hvor mange poster som vil være i den tilsvarende tabellen), og hvor ofte den brukes i andre funksjoner.

analoger

Moderne kommersielle DBMS-er har lignende mekanismer: MATERIALISERT VISNING med FAST REFRESH (Oracle) og INDEXED VIEW (Microsoft SQL Server). I PostgreSQL kan MATERIALIZED VIEW ikke oppdateres i en transaksjon, men kun på forespørsel (og til og med med svært strenge restriksjoner), så vi vurderer det ikke. Men de har flere problemer som begrenser bruken betydelig.

For det første kan du bare aktivere materialisering hvis du allerede har opprettet en vanlig VIEW. Ellers må du skrive om de gjenværende forespørslene for å få tilgang til den nyopprettede visningen for å bruke denne materialiseringen. Eller la alt være som det er, men det vil i det minste være ineffektivt hvis det er visse allerede forhåndsberegnet data, men mange spørringer bruker det ikke alltid, men beregner det på nytt.

For det andre har de et stort antall restriksjoner:

Oracle

5.3.8.4 Generelle restriksjoner på hurtigoppdatering

Den definerende spørringen for den materialiserte visningen er begrenset som følger:

  • Det materialiserte synet må ikke inneholde referanser til ikke-repeterende uttrykk som SYSDATE og ROWNUM.
  • Det materialiserte synet må ikke inneholde referanser til RAW or LONG RAW datatyper.
  • Den kan ikke inneholde en SELECT liste underspørring.
  • Den kan ikke inneholde analytiske funksjoner (f.eks. RANK) I SELECT klausul.
  • Den kan ikke referere til en tabell der en XMLIndex indeks er definert.
  • Den kan ikke inneholde en MODEL klausul.
  • Den kan ikke inneholde en HAVING klausul med en underspørring.
  • Den kan ikke inneholde nestede søk som har ANY, ALLeller NOT EXISTS.
  • Den kan ikke inneholde en [START WITH …] CONNECT BY klausul.
  • Den kan ikke inneholde flere detaljtabeller på forskjellige steder.
  • ON COMMIT materialiserte visninger kan ikke ha eksterne detaljtabeller.
  • Nestede materialiserte visninger må ha en sammenføyning eller aggregat.
  • Materialiserte sammenføyningsvisninger og materialiserte aggregerte visninger med en GROUP BY klausul kan ikke velge fra en indeksorganisert tabell.

5.3.8.5 Restriksjoner på rask oppdatering på materialiserte visninger med bare sammenføyninger

Definering av søk for materialiserte visninger med bare sammenføyninger og ingen aggregater har følgende begrensninger for rask oppdatering:

  • Alle restriksjoner fra «Generelle begrensninger for rask oppdatering".
  • De kan ikke ha GROUP BY klausuler eller aggregater.
  • Rowids av alle tabellene i FROM listen må vises i SELECT listen over spørringen.
  • Materialiserte visningslogger må eksistere med rader for alle basistabellene i FROM listen over spørringen.
  • Du kan ikke lage en raskt oppdaterbar materialisert visning fra flere tabeller med enkle sammenføyninger som inkluderer en objekttypekolonne i SELECT uttalelse.

Oppdateringsmetoden du velger vil heller ikke være optimalt effektiv hvis:

  • Den definerende spørringen bruker en ytre sammenføyning som oppfører seg som en indre sammenføyning. Hvis den definerende spørringen inneholder en slik sammenføyning, bør du vurdere å omskrive den definerende spørringen til å inneholde en indre sammenføyning.
  • De SELECT listen over den materialiserte visningen inneholder uttrykk på kolonner fra flere tabeller.

5.3.8.6 Begrensninger for rask oppdatering på materialiserte visninger med aggregater

Definering av søk for materialiserte visninger med aggregater eller sammenføyninger har følgende begrensninger for hurtigoppdatering:

Rask oppdatering støttes for begge ON COMMIT og ON DEMAND materialiserte visninger, men følgende begrensninger gjelder:

  • Alle tabeller i den materialiserte visningen må ha materialiserte visningslogger, og de materialiserte visningsloggene må:
    • Inneholder alle kolonnene fra tabellen det refereres til i den materialiserte visningen.
    • Spesifiser med ROWID og INCLUDING NEW VALUES.
    • Spesifiser SEQUENCE klausul hvis tabellen forventes å ha en blanding av innsettinger/direkte innlastinger, slettinger og oppdateringer.

  • Bare SUM, COUNT, AVG, STDDEV, VARIANCE, MIN og MAX støttes for rask oppdatering.
  • COUNT(*) må spesifiseres.
  • Aggregerte funksjoner må kun forekomme som den ytterste delen av uttrykket. Det vil si aggregater som f.eks AVG(AVG(x)) or AVG(x)+ AVG(x) er ikke lov.
  • For hvert aggregat som f.eks AVG(expr), det tilsvarende COUNT(expr) må være tilstede. Oracle anbefaler det SUM(expr) spesifiseres.
  • If VARIANCE(expr) or STDDEV(expr) er spesifisert, COUNT(expr) og SUM(expr) må spesifiseres. Oracle anbefaler det SUM(expr *expr) spesifiseres.
  • De SELECT kolonnen i den definerende spørringen kan ikke være et komplekst uttrykk med kolonner fra flere basistabeller. En mulig løsning på dette er å bruke en nestet materialisert visning.
  • De SELECT listen må inneholde alle GROUP BY kolonner.
  • Den materialiserte visningen er ikke basert på en eller flere eksterne tabeller.
  • Hvis du bruker en CHAR datatype i filterkolonnene i en materialisert visningslogg, må tegnsettene til hovednettstedet og den materialiserte visningen være de samme.
  • Hvis den materialiserte visningen har ett av følgende, støttes rask oppdatering kun på konvensjonelle DML-innlegg og direkte lastinger.
    • Materialiserte visninger med MIN or MAX aggregater
    • Materialiserte synspunkter som har SUM(expr) men nei COUNT(expr)
    • Materialiserte utsikter uten COUNT(*)

    Et slikt materialisert syn kalles et materialisert syn som kun kan settes inn.

  • Et materialisert syn med MAX or MIN kan raskt oppdateres etter sletting eller blandede DML-setninger hvis den ikke har en WHERE klausul.
    Maks/min hurtigoppdatering etter sletting eller blandet DML har ikke samme virkemåte som bare innsetting. Den sletter og beregner maks/min-verdiene for de berørte gruppene på nytt. Du må være klar over dens ytelseseffekt.
  • Materialiserte visninger med navngitte visninger eller underspørringer i FROM klausulen kan raskt oppdateres forutsatt at visningene kan slås helt sammen. For informasjon om hvilke visninger som vil slå seg sammen, se Oracle Database SQL Language Reference.
  • Hvis det ikke er noen ytre sammenføyninger, kan du ha vilkårlige valg og sammenføyninger i WHERE klausul.
  • Materialiserte aggregerte visninger med ytre skjøter kan raskt oppdateres etter konvensjonell DML og direkte belastninger, forutsatt at bare den ytre tabellen er modifisert. Det må også finnes unike begrensninger på sammenføyningskolonnene i den indre sammenføyningstabellen. Hvis det er ytre skjøter, må alle skjøtene forbindes med ANDs og må bruke likheten (=) operatør.
  • For materialiserte visninger med CUBE, ROLLUP, grupperingssett eller sammenkobling av dem, gjelder følgende begrensninger:
    • De SELECT listen bør inneholde gruppering skiller som enten kan være en GROUPING_ID funksjon på alle GROUP BY uttrykk eller GROUPING funksjoner en for hver GROUP BY uttrykk. For eksempel, hvis GROUP BY klausulen i det materialiserte synet er "GROUP BY CUBE(a, b)", og så SELECT listen skal inneholde enten "GROUPING_ID(a, b)» eller «GROUPING(a) AND GROUPING(b)» for at den materialiserte visningen raskt kan oppdateres.
    • GROUP BY bør ikke resultere i dupliserte grupperinger. For eksempel, "GROUP BY a, ROLLUP(a, b)" kan ikke oppdateres raskt fordi det resulterer i dupliserte grupperinger "(a), (a, b), AND (a)".

5.3.8.7 Restriksjoner på rask oppdatering på materialiserte visninger med UNION ALL

Materialiserte utsikter med UNION ALL sett operatørstøtte REFRESH FAST alternativ hvis følgende betingelser er oppfylt:

  • Den definerende spørringen må ha UNION ALL operatør på toppnivå.

    De UNION ALL operatør kan ikke bygges inn i en underspørring, med ett unntak: The UNION ALL kan være i en underspørring i FROM klausul forutsatt at den definerende spørringen er av formen SELECT * FROM (vis eller undersøk med UNION ALL) som i følgende eksempel:

    CREATE VIEW view_with_unionall AS (VELG c.rowid crid, c.cust_id, 2 umarker FROM kunder c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM kunder c WHERE c.cust_last_name = 'Jones'); LAG MATERIALISERT VISNING unionall_inside_view_mv OPPDATER RASK PÅ DEMAND SOM VELG * FRA view_with_unionall;
    

    Merk at utsikten view_with_unionall tilfredsstiller kravene til rask oppdatering.

  • Hver spørringsblokk i UNION ALL spørringen må tilfredsstille kravene til en raskt oppdaterbar materialisert visning med aggregater eller en raskt oppdaterbar materialisert visning med sammenføyninger.

    De riktige materialiserte visningsloggene må opprettes på tabellene etter behov for den tilsvarende typen raskt oppdaterbar materialisert visning.
    Legg merke til at Oracle-databasen også tillater det spesielle tilfellet med en enkelt tabellmaterialisert visning med sammenføyninger kun forutsatt at ROWID kolonnen er inkludert i SELECT listen og i den materialiserte visningsloggen. Dette vises i den definerende spørringen til visningen view_with_unionall.

  • De SELECT listen over hvert søk må inneholde en UNION ALL markør, og UNION ALL kolonne må ha en distinkt konstant numerisk eller strengverdi i hver UNION ALL gren. Videre må markørkolonnen vises i samme ordensposisjon i SELECT liste over hver spørringsblokk. Se "UNION ALL Marker og Query Rewrite» for mer informasjon vedr UNION ALL markører.
  • Noen funksjoner, for eksempel ytre sammenføyninger, innsetting av aggregerte materialiserte visningsspørringer og eksterne tabeller, støttes ikke for materialiserte visninger med UNION ALL. Vær imidlertid oppmerksom på at materialiserte visninger brukt i replikering, som ikke inneholder sammenføyninger eller aggregater, raskt kan oppdateres når UNION ALL eller eksterne tabeller brukes.
  • Kompatibilitetsinitieringsparameteren må settes til 9.2.0 eller høyere for å lage en raskt oppdaterbar materialisert visning med UNION ALL.

Jeg vil ikke fornærme Oracle-fans, men å dømme etter listen over restriksjoner, ser det ut til at denne mekanismen ikke ble skrevet i den generelle saken, ved å bruke en slags modell, men av tusenvis av indere, der alle fikk muligheten til å skriv sin egen gren, og hver av dem gjorde det han kunne og gjorde. Å bruke denne mekanismen for ekte logikk er som å gå gjennom et minefelt. Du kan få en mine når som helst ved å trykke på en av de ikke-åpenbare restriksjonene. Hvordan det fungerer er også et eget spørsmål, men det er utenfor rammen av denne artikkelen.

Microsoft SQL Server

Tilleggskrav

I tillegg til SET-alternativene og deterministiske funksjonskravene, må følgende krav oppfylles:

  • Brukeren som kjører CREATE INDEX må være eier av utsikten.
  • Når du oppretter indeksen, vil IGNORE_DUP_KEY alternativet må settes til AV (standardinnstillingen).
  • Tabeller må refereres med todelte navn, skjema.tabellnavn i visningsdefinisjonen.
  • Brukerdefinerte funksjoner referert til i visningen må opprettes ved å bruke WITH SCHEMABINDING alternativet.
  • Alle brukerdefinerte funksjoner referert til i visningen må refereres til med todelte navn, ..
  • Datatilgangsegenskapen til en brukerdefinert funksjon må være NO SQL, og ekstern tilgang eiendom må være NO.
  • Common Language runtime (CLR)-funksjoner kan vises i utvalgslisten til visningen, men kan ikke være en del av definisjonen av den grupperte indeksnøkkelen. CLR-funksjoner kan ikke vises i WHERE-leddet i visningen eller ON-leddet til en JOIN-operasjon i visningen.
  • CLR-funksjoner og -metoder for CLR-brukerdefinerte typer brukt i visningsdefinisjonen må ha egenskapene angitt som vist i følgende tabell.

    Eiendom
    Merknader

    DETERMINISTISK = SANN
    Må deklareres eksplisitt som et attributt for Microsoft .NET Framework-metoden.

    NØYAKTIG = SANN
    Må deklareres eksplisitt som et attributt for .NET Framework-metoden.

    DATA TILGANG = INGEN SQL
    Bestemmes ved å sette DataAccess-attributtet til DataAccessKind.None og SystemDataAccess-attributtet til SystemDataAccessKind.None.

    EKSTERN TILGANG = NR
    Denne egenskapen er som standard NO for CLR-rutiner.

  • Visningen må opprettes ved å bruke WITH SCHEMABINDING alternativet.
  • Utsnittet må kun referere til basistabeller som er i samme database som utsnittet. Visningen kan ikke referere til andre synspunkter.
  • SELECT-setningen i visningsdefinisjonen må ikke inneholde følgende Transact-SQL-elementer:

    COUNT
    ROWSET-funksjoner (OPENDATASOURCE, OPENQUERY, OPENROWSET, OG OPENXML)
    OUTER blir med (LEFT, RIGHTeller FULL)

    Avledet tabell (definert ved å spesifisere en SELECT uttalelse i FROM klausul)
    Selv blir med
    Spesifisere kolonner ved å bruke SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARPeller AVG
    Felles tabelluttrykk (CTE)

    flyte1, tekst, ntekst, bilde, XMLeller filstrøm kolonner
    delspørring
    OVER klausul, som inkluderer rangering eller aggregerte vindusfunksjoner

    Fulltekstpredikater (CONTAINS, FREETEXT)
    SUM funksjon som refererer til et nullbart uttrykk
    ORDER BY

    CLR brukerdefinert aggregatfunksjon
    TOP
    CUBE, ROLLUPeller GROUPING SETS operatører

    MIN, MAX
    UNION, EXCEPTeller INTERSECT operatører
    TABLESAMPLE

    Tabellvariabler
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Sparsomme søylesett
    Inline (TVF) eller multi-statement table-valued functions (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Den indekserte visningen kan inneholde flyte kolonner; slike kolonner kan imidlertid ikke inkluderes i den grupperte indeksnøkkelen.

  • If GROUP BY er tilstede, må VIEW-definisjonen inneholde COUNT_BIG(*) og må ikke inneholde HAVING. Disse GROUP BY restriksjoner gjelder bare for definisjonen av indeksert visning. En spørring kan bruke en indeksert visning i sin utførelsesplan selv om den ikke tilfredsstiller disse GROUP BY begrensninger.
  • Hvis visningsdefinisjonen inneholder en GROUP BY klausul, kan nøkkelen til den unike grupperte indeksen kun referere til kolonnene som er spesifisert i GROUP BY klausul.

Det er tydelig her at indianerne ikke var involvert, siden de bestemte seg for å gjøre det i henhold til ordningen "vi vil gjøre lite, men godt." Det vil si at de har flere miner på feltet, men deres plassering er mer oversiktlig. Det mest skuffende er denne begrensningen:

Utsnittet må kun referere til basistabeller som er i samme database som utsnittet. Visningen kan ikke referere til andre synspunkter.

I vår terminologi betyr dette at en funksjon ikke kan få tilgang til en annen materialisert funksjon. Dette kutter ned all ideologi i knoppen.
Dessuten reduserer denne begrensningen (og videre i teksten) brukstilfellene:

SELECT-setningen i visningsdefinisjonen må ikke inneholde følgende Transact-SQL-elementer:

COUNT
ROWSET-funksjoner (OPENDATASOURCE, OPENQUERY, OPENROWSET, OG OPENXML)
OUTER blir med (LEFT, RIGHTeller FULL)

Avledet tabell (definert ved å spesifisere en SELECT uttalelse i FROM klausul)
Selv blir med
Spesifisere kolonner ved å bruke SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARPeller AVG
Felles tabelluttrykk (CTE)

flyte1, tekst, ntekst, bilde, XMLeller filstrøm kolonner
delspørring
OVER klausul, som inkluderer rangering eller aggregerte vindusfunksjoner

Fulltekstpredikater (CONTAINS, FREETEXT)
SUM funksjon som refererer til et nullbart uttrykk
ORDER BY

CLR brukerdefinert aggregatfunksjon
TOP
CUBE, ROLLUPeller GROUPING SETS operatører

MIN, MAX
UNION, EXCEPTeller INTERSECT operatører
TABLESAMPLE

Tabellvariabler
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Sparsomme søylesett
Inline (TVF) eller multi-statement table-valued functions (MSTVF)
OFFSET

CHECKSUM_AGG

OUTER JOINS, UNION, ORDER BY og andre er forbudt. Det kan ha vært lettere å spesifisere hva som kunne brukes fremfor hva som ikke kunne brukes. Listen ville nok vært mye kortere.

For å oppsummere: et stort sett med begrensninger i hver (la oss merke kommersielle) DBMS vs ingen (med unntak av en logisk, ikke teknisk) i LGPL-teknologi. Det skal imidlertid bemerkes at implementering av denne mekanismen i relasjonslogikk er noe vanskeligere enn i den beskrevne funksjonelle logikken.

implementering

Hvordan det fungerer? PostgreSQL brukes som en "virtuell maskin". Det er en kompleks algoritme inne som bygger spørringer. Her kilde. Og det er ikke bare et stort sett med heuristikk med en haug med hvis. Så hvis du har et par måneder på deg til å studere, kan du prøve å forstå arkitektur.

Fungerer det effektivt? Ganske effektivt. Dessverre er dette vanskelig å bevise. Jeg kan bare si at hvis du vurderer de tusenvis av forespørsler som finnes i store applikasjoner, så er de i gjennomsnitt mer effektive enn de til en god utvikler. En utmerket SQL-programmerer kan skrive alle spørringer mer effektivt, men med tusen spørringer vil han rett og slett ikke ha motivasjon eller tid til å gjøre det. Det eneste jeg nå kan sitere som bevis på effektivitet er at flere prosjekter jobber på plattformen bygget på dette DBMS ERP-systemer, som har tusenvis av forskjellige MATERIALISERT-funksjoner, med tusenvis av brukere og terabyte-databaser med hundrevis av millioner poster som kjører på en vanlig to-prosessor server. Men hvem som helst kan sjekke/avkrefte effektiviteten ved å laste ned plattform og PostgreSQL, skrudd på logger SQL-spørringer og prøver å endre logikken og dataene der.

I de følgende artiklene vil jeg også snakke om hvordan du kan sette begrensninger på funksjoner, jobbe med endringsøkter og mye mer.

Kilde: www.habr.com

Legg til en kommentar