Balansearjen fan skriuwt en lêzen yn in databank

Balansearjen fan skriuwt en lêzen yn in databank
Yn it foarige artikel Ik beskreau it konsept en ymplemintaasje fan in databank boud op basis fan funksjes, ynstee fan tabellen en fjilden lykas yn relasjonele databases. It levere in protte foarbylden dy't de foardielen fan dizze oanpak sjen litte oer de klassike. In protte fûnen har net oertsjûgjend genôch.

Yn dit artikel sil ik sjen litte hoe't mei dit konsept jo fluch en maklik it skriuwen en it lêzen yn 'e database kinne balansearje sûnder feroaring yn' e bestjoeringslogika. Fergelykbere funksjonaliteit is besocht te ymplementearjen yn moderne kommersjele DBMS's (benammen Oracle en Microsoft SQL Server). Oan 'e ein fan it artikel sil ik sjen litte dat wat se diene, om it myld te sizzen, net sa goed slagge.

beskriuwing

Lykas earder sil ik foar better begryp de beskriuwing begjinne mei foarbylden. Litte wy sizze dat wy logika moatte ymplementearje dy't in list fan ôfdielingen sil weromjaan mei it oantal meiwurkers yn har en har totale salaris.

Yn in funksjonele databank soe it der sa útsjen:

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

De kompleksiteit fan it útfieren fan dizze query yn elke DBMS sil lykweardich wêze oan O (oantal meiwurkers)omdat dizze berekkening fereasket skennen fan de hiele tabel fan meiwurkers en dan groepearje se troch ôfdieling. Der sil ek wat lytse (wy leauwe dat der folle mear meiwurkers as ôfdielings) oanfolling ôfhinklik fan it keazen plan O (log oantal meiwurkers) of O (oantal ôfdielings) foar groepearring ensafuorthinne.

It is dúdlik dat de útfieringsoverhead kin oars wêze yn ferskate DBMS's, mar de kompleksiteit sil op gjin inkelde manier feroarje.

Yn 'e foarstelde ymplemintaasje sil de funksjonele DBMS ien subquery generearje dy't de fereaske wearden foar de ôfdieling sil berekkenje, en dan in JOIN meitsje mei de ôfdielingstabel om de namme te krijen. Foar elke funksje is it lykwols mooglik om in spesjale MATERIALIZED marker yn te stellen by it ferklearjen. It systeem sil automatysk in oerienkommende fjild meitsje foar elke sa'n funksje. By it feroarjen fan de wearde fan in funksje sil de wearde fan it fjild ek feroarje yn deselde transaksje. By tagong ta dizze funksje wurdt tagong ta it foarberekkene fjild.

Benammen as jo MATERIALIZED ynstelle foar funksjes count Employees и salarisSum, dan wurde twa fjilden tafoege oan 'e tabel mei de list fan ôfdielingen, dy't it oantal meiwurkers en har totale salaris opslaan. Wannear't d'r in feroaring is yn meiwurkers, har salarissen of ôfdielingsferbannen, sil it systeem automatysk de wearden fan dizze fjilden feroarje. De boppesteande query sil direkt tagong krije ta dizze fjilden en sil wurde útfierd yn O (oantal ôfdielings).

Wat binne de beheiningen? Allinich ien ding: sa'n funksje moat in einich oantal ynfierwearden hawwe wêrfoar de wearde is definieare. Oars sil it ûnmooglik wêze om in tabel te bouwen dy't al syn wearden opslacht, om't d'r gjin tabel kin wêze mei in ûneinich oantal rigen.

Foarbyld:

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

Dizze funksje is definiearre foar in ûneinich oantal wearden fan N (bygelyks elke negative wearde is geskikt). Dêrom kinne jo der net MATERIALIZED op sette. Dat dit is in logyske beheining, net in technyske (dat is, net om't wy it net kinne ymplementearje). Oars binne d'r gjin beheiningen. Jo kinne groepearrings, sortearring, EN en OR, PARTISJE, rekursje, ensfh.

Bygelyks, yn probleem 2.2 fan it foarige artikel kinne jo MATERIALIZED op beide funksjes sette:

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;

It systeem sels sil ien tabel meitsje mei typekaaien Klant, Product и YNTEGER, sil der twa fjilden oan tafoegje en de fjildwearden dêryn bywurkje mei alle feroaringen. As fierdere oproppen nei dizze funksjes wurde makke, sille se net wurde berekkene, mar leaver wurde de wearden lêzen út 'e oerienkommende fjilden.

Mei dit meganisme kinne jo bygelyks recursions (CTE) kwytreitsje yn queries. Besjoch benammen groepen dy't in beam foarmje mei de bern/âlder-relaasje (elke groep hat in keppeling nei har âlder):

parent = DATA Group (Group);

Yn in funksjonele databank kin rekursjelogika as folgjend oanjûn wurde:

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;

Sûnt foar de funksje isParent is markearre MATERIALIZED, dan sil der in tabel mei twa kaaien (groepen) foar makke wurde, wêryn it fjild isParent sil wier wêze allinne as de earste kaai is in bern fan de twadde. It oantal yngongen yn dizze tabel sil gelyk wêze oan it oantal groepen fermannichfâldige mei de gemiddelde djipte fan 'e beam. As jo ​​​​bygelyks it oantal neikommelingen fan in bepaalde groep moatte telle, kinne jo dizze funksje brûke:

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

D'r sil gjin CTE wêze yn 'e SQL-query. Ynstee komt der in ienfâldige GROUP BY.

Mei dit meganisme kinne jo de databank ek maklik denormalisearje as it nedich is:

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

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

By it roppen fan in funksje datum foar de oarderrigel wurdt it fjild dêr't in yndeks foar is lêzen út de tabel mei oarderrigels. As de bestellingsdatum feroaret, sil it systeem sels de denormalisearre datum yn 'e line automatysk opnij berekkenje.

foardielen

Wat is dit hiele meganisme foar? Yn klassike DBMS's, sûnder query's te herskriuwen, kin in ûntwikkelder as DBA allinich yndeksen feroarje, statistiken bepale en de queryplanner fertelle hoe't se se útfiere (en HINT's binne allinich beskikber yn kommersjele DBMS's). Hoe hurd se ek besykje, se sille de earste fraach yn it artikel yn net kinne foltôgje O (oantal ôfdielings) sûnder queries te feroarjen of triggers ta te foegjen. Yn it foarstelde skema hoege jo yn 'e ûntwikkelingsstadium net te tinken oer de gegevensopslachstruktuer en hokker aggregaasjes te brûken. Dit alles kin maklik feroare wurde op 'e flecht, direkt yn wurking.

Yn de praktyk sjocht it der sa út. Guon minsken ûntwikkelje logika direkt basearre op 'e taak by de hân. Se begripe gjin algoritmen en har kompleksiteit, noch útfieringsplannen, noch soarten joins, noch in oare technyske komponint. Dizze minsken binne mear saaklike analisten dan ûntwikkelders. Dan giet dit alles yn testen as operaasje. Aktivearret logging fan lange-rinnende queries. As in lange fraach wurdt ûntdutsen, dan beslute oare minsken (technysk - yn essinsje DBA) om MATERIALIZED yn te skeakeljen op ien of oare tuskenfunksje. Dit vertraagt ​​de opname in bytsje (om't it fereasket it bywurkjen fan in ekstra fjild yn 'e transaksje). Lykwols, net allinnich dizze query wurdt gâns fersneld, mar ek alle oaren dy't brûke dizze funksje. Tagelyk, it besluten hokker funksje te materialisearjen is relatyf maklik. Twa haadparameters: it oantal mooglike ynfierwearden (dit is hoefolle records sille wêze yn 'e oerienkommende tabel), en hoe faak it wurdt brûkt yn oare funksjes.

Analogen

Moderne kommersjele DBMS's hawwe ferlykbere meganismen: MATERIALIZED VIEW mei FAST REFRESH (Oracle) en INDEXED VIEW (Microsoft SQL Server). Yn PostgreSQL kin MATERIALIZED VIEW net bywurke wurde yn in transaksje, mar allinich op oanfraach (en sels mei heul strikte beheiningen), dus wy beskôgje it net. Mar se hawwe ferskate problemen dy't har gebrûk signifikant beheine.

As earste kinne jo materialisaasje allinich ynskeakelje as jo al in gewoane VIEW hawwe makke. Oars moatte jo de oerbleaune oanfragen opnij skriuwe om tagong te krijen ta de nij oanmakke werjefte om dizze materialisaasje te brûken. Of lit alles sa't it is, mar it sil op syn minst net effektyf wêze as d'r bepaalde al foarberekkene gegevens binne, mar in protte fragen brûke it net altyd, mar berekkenje it opnij.

Twadder hawwe se in enoarm oantal beheiningen:

Oracle

5.3.8.4 Algemiene beheiningen op Fast Refresh

De definiearjende fraach fan 'e materialisearre werjefte is as folget beheind:

  • De materialisearre werjefte moat gjin ferwizings befetsje nei net-werheljende útdrukkingen lykas SYSDATE en ROWNUM.
  • De materialisearre werjefte moat gjin ferwizings nei RAW or LONG RAW gegevens typen.
  • It kin net befetsje in SELECT list subquery.
  • It kin gjin analytyske funksjes befetsje (bygelyks, RANK) yn de SELECT klausule.
  • It kin net ferwize nei in tabel dêr't in XMLIndex yndeks wurdt definiearre.
  • It kin net befetsje in MODEL klausule.
  • It kin net befetsje in HAVING klausule mei in subquery.
  • It kin net befetsje geneste queries dy't hawwe ANY, ALL, of NOT EXISTS.
  • It kin net befetsje in [START WITH …] CONNECT BY klausule.
  • It kin net befetsje meardere detail tabellen op ferskillende siden.
  • ON COMMIT materialized views kinne net hawwe remote detail tabellen.
  • Neste materialisearre werjeften moatte in join of aggregaat hawwe.
  • Materialisearre join werjeften en materialisearre aggregearre werjeften mei in GROUP BY clause kin net selektearje út in yndeks-organisearre tabel.

5.3.8.5 Beperkingen op fluch ferfarskje op materialisearre werjeften mei allinich joins

It definiearjen fan fragen foar materialisearre werjeften mei allinich joins en gjin aggregaten hawwe de folgjende beheiningen foar rappe ferfarsk:

  • Alle beheiningen fan «Algemiene beheiningen op Fast Refresh".
  • Se kinne net hawwe GROUP BY klausules of aggregaten.
  • Rowids fan alle tabellen yn 'e FROM list moat ferskine yn 'e SELECT list fan de query.
  • Materialisearre werjefte logs moatte bestean mei rowids foar alle basis tabellen yn 'e FROM list fan de query.
  • Jo kinne gjin fluch ferfarsbere materialisearre werjefte meitsje fan meardere tabellen mei ienfâldige joins dy't in objekttypekolom yn 'e SELECT ferklearring.

Ek sil de ferfarskingsmetoade dy't jo kieze net optimaal effisjint wêze as:

  • De definiearjende query brûkt in eksterne join dy't him gedraacht as in ynderlike join. As de definiearjende query sa'n join befettet, beskôgje dan it oerskriuwen fan de definiearjende query om in ynderlike join te befetsjen.
  • De SELECT list fan de materialized werjefte befettet útdrukkingen op kolommen út meardere tabellen.

5.3.8.6 Beperkingen op fluch ferfarskje op materialisearre werjeften mei aggregaten

It definiearjen fan queries foar materialisearre werjeften mei aggregaten of joins hawwe de folgjende beheiningen foar rappe ferfarsking:

Snelle ferfarsking wurdt stipe foar beide ON COMMIT en ON DEMAND materialisearre werjeften, lykwols jilde de folgjende beheiningen:

  • Alle tabellen yn 'e materialisearre werjefte moatte materialisearre werjeftelogboeken hawwe, en de materialisearre werjeftelogboeken moatte:
    • Befette alle kolommen út 'e tabel ferwiisd yn' e materialisearre werjefte.
    • Spesifisearje mei ROWID en INCLUDING NEW VALUES.
    • Jou de SEQUENCE klausule as de tabel wurdt ferwachte dat se in miks hawwe fan ynfoegingen / direkte laden, wiskjen en fernijings.

  • Allinnich SUM, COUNT, AVG, STDDEV, VARIANCE, MIN en MAX wurde stipe foar rappe ferfarsking.
  • COUNT(*) moat wurde oantsjutte.
  • Aggregearre funksjes moatte allinich foarkomme as it bûtenste diel fan 'e útdrukking. Dat is, aggregaten lykas AVG(AVG(x)) or AVG(x)+ AVG(x) binne net tastien.
  • Foar elke aggregaat lykas AVG(expr), de oerienkommende COUNT(expr) moat oanwêzich wêze. Oracle advisearret dat SUM(expr) wurde spesifisearre.
  • If VARIANCE(expr) or STDDEV(expr) is spesifisearre, COUNT(expr) en SUM(expr) moat wurde oantsjutte. Oracle advisearret dat SUM(expr *expr) wurde spesifisearre.
  • De SELECT kolom yn de defining query kin net wêze in komplekse útdrukking mei kolommen út meardere basis tabellen. In mooglike oplossing foar dit is it brûken fan in geneste materialisearre werjefte.
  • De SELECT list moat befetsje alles GROUP BY pylder.
  • De materialisearre werjefte is net basearre op ien of mear tabellen op ôfstân.
  • As jo ​​in CHAR gegevenstype yn 'e filterkolommen fan in materialisearre werjeftelog, moatte de karaktersets fan 'e masterside en de materialisearre werjefte itselde wêze.
  • As de materialisearre werjefte ien fan 'e folgjende hat, dan wurdt rappe ferfarsk allinich stipe op konvinsjonele DML-ynfoegingen en direkte loads.
    • Materialisearre views mei MIN or MAX aggregaten
    • Materialisearre views dy't hawwe SUM(expr) mar nee COUNT(expr)
    • Materialisearre views sûnder COUNT(*)

    Sa'n materialisearre werjefte wurdt in ynset-allinich materialisearre werjefte neamd.

  • In materialisearre werjefte mei MAX or MIN is fluch refreshable nei wiskjen of mingde DML útspraken as it hat gjin in WHERE klausule.
    De max/min snelle ferfarsking nei wiskjen of mingde DML hat net itselde gedrach as it gefal mei allinich ynfoegje. It wisket en berekkent de max / min wearden foar de troffen groepen. Jo moatte bewust wêze fan har prestaasjesynfloed.
  • Materialisearre werjeften mei neamde werjeften of subqueries yn 'e FROM klausule kin fluch wurde ferfarske mits de werjeften kinne wurde folslein gearfoege. Foar ynformaasje oer hokker werjeften sille fusearje, sjoch Oracle Database SQL Language Reference.
  • As der gjin bûtenste joins, Jo meie hawwe willekeurich seleksjes en joins yn de WHERE klausule.
  • Materialisearre aggregaat werjeften mei bûtenste joins binne fluch ferfarskber nei konvinsjonele DML en direkte loads, mits allinnich de bûtenste tafel is wizige. Ek moatte unike beheinings bestean op 'e join kolommen fan' e binnenste join tabel. As der bûtenste joins, alle joins moatte wurde ferbûn troch ANDs en moat de gelikensens brûke (=) operator.
  • Foar materialized views mei CUBE, ROLLUP, groepsets, of gearhing dêrfan, jilde de folgjende beheiningen:
    • De SELECT list moat befetsje groepearring distinguisher dat kin of wêze in GROUPING_ID funksje op alle GROUP BY útdrukkingen of GROUPING funksjonearret ien foar elk GROUP BY útdrukking. Bygelyks, as de GROUP BY klausule fan 'e materialisearre werjefte is "GROUP BY CUBE(a, b)", dan de SELECT list moat befetsje "GROUPING_ID(a, b)» of «GROUPING(a) AND GROUPING(b)» foar de materialisearre werjefte om rap ferfarskber te wêzen.
    • GROUP BY moat net resultearje yn dûbele groepearrings. Bygelyks, "GROUP BY a, ROLLUP(a, b)" is net fluch ferfarskber omdat it resulteart yn dûbele groepearrings "(a), (a, b), AND (a)".

5.3.8.7 Beperkingen op fluch ferfarskje op materialisearre werjeften mei UNION ALL

Materialized views mei de UNION ALL set operator stipe de REFRESH FAST opsje as de folgjende betingsten foldien binne:

  • De definiearjende query moat de UNION ALL operator op it boppeste nivo.

    De UNION ALL operator kin net ynbêde yn in subquery, mei ien útsûndering: De UNION ALL kin wêze yn in subquery yn 'e FROM klausule op betingst dat de definiearjende fraach fan 'e foarm is SELECT * FROM (besjoch of subquery mei UNION ALL) lykas yn it folgjende foarbyld:

    CREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM klanten c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM klanten c WHERE c.cust_last_name = 'Jones'); CREATE MATERIALIZED VIEW unionall_inside_view_mv REFRESH FAST ON DEMAND AS SELECT * FROM view_with_unionall;
    

    Tink derom dat de werjefte view_with_unionall foldocht oan de easken foar snelle ferfarsking.

  • Elke query blok yn 'e UNION ALL query moat foldwaan oan de easken fan in fluch ferfarskber materialisearre werjefte mei aggregaten of in fluch ferfarskbere materialisearre werjefte mei joins.

    De passende materialisearre werjefte logs moatte wurde oanmakke op 'e tabellen as nedich foar de oerienkommende soarte fan fluch ferfarskber materialized werjefte.
    Tink derom dat de Oracle Database ek kinne it spesjale gefal fan in inkele tabel materialized werjefte mei joins allinnich foarsjoen fan de ROWID kolom is opnommen yn 'e SELECT list en yn 'e materialisearre werjeftelog. Dit wurdt werjûn yn 'e definiearjende query fan 'e werjefte view_with_unionall.

  • De SELECT list fan elke query moat befetsje in UNION ALL marker, en de UNION ALL kolom moat in ûnderskate konstante numerike of tekenrige wearde yn elk hawwe UNION ALL tûke. Fierder moat de marker kolom ferskine yn deselde ordinale posysje yn 'e SELECT list fan elk query blok. Sjoch "UNION ALL Marker en Query Rewrite» foar mear ynformaasje oangeande UNION ALL markearders.
  • Guon funksjes lykas outer joins, aggregearre werjeftefragen dy't allinich ynfoegje en tabellen op ôfstân wurde net stipe foar materialisearre werjeften mei UNION ALL. Tink derom lykwols dat materialisearre werjeften brûkt yn replikaasje, dy't gjin joins of aggregaten befetsje, rap kinne wurde ferfarske as UNION ALL of op ôfstân tabellen wurde brûkt.
  • De kompatibiliteitsinisjalisaasjeparameter moat ynsteld wurde op 9.2.0 of heger om in fluch ferfarskbere materialisearre werjefte te meitsjen mei UNION ALL.

Ik wol Oracle-fans net misledigje, mar beoardielje troch har list mei beheiningen, liket it derop dat dit meganisme net yn 't algemien skreaun is, mei in soarte fan model, mar troch tûzenen Yndianen, wêr't elkenien de kâns krige om skriuw har eigen tûke, en elk fan harren die wat er koe en die. It brûken fan dit meganisme foar echte logika is as kuierjen troch in minefjild. Jo kinne op elk momint in myn krije troch ien fan 'e net-foar de hân lizzende beheiningen te reitsjen. Hoe't it wurket is ek in aparte fraach, mar it is bûten it berik fan dit artikel.

Microsoft SQL-tsjinner

Oanfoljende easken

Neist de SET-opsjes en deterministyske funksje-easken moatte de folgjende easken foldien wurde:

  • De brûker dy't útfiert CREATE INDEX moat de eigner fan it útsicht wêze.
  • As jo ​​meitsje de yndeks, de IGNORE_DUP_KEY opsje moat ynsteld wurde op OFF (de standertynstelling).
  • Tabellen moatte wurde ferwiisd troch twa-dielige nammen, schema.tabelnamme yn de werjefte definysje.
  • Meidogger-definiearre funksjes ferwiisd yn de werjefte moatte wurde makke mei help fan de WITH SCHEMABINDING opsje.
  • Elke troch de brûker definieare funksjes ferwiisd yn 'e werjefte moatte wurde ferwiisd troch twadielige nammen, ..
  • De eigenskip foar gegevenstagong fan in troch de brûker definieare funksje moat wêze NO SQL, en eksterne tagong eigendom moat wêze NO.
  • Common language runtime (CLR) funksjes kinne ferskine yn de selektearre list fan de werjefte, mar kin gjin diel útmeitsje fan de definysje fan de klustere yndeks kaai. CLR-funksjes kinne net ferskine yn 'e WHERE-klausule fan' e werjefte of de ON-klausule fan in JOIN-operaasje yn 'e werjefte.
  • CLR funksjes en metoaden fan CLR brûker-definiearre typen brûkt yn de werjefte definysje moatte hawwe de eigenskippen ynsteld lykas werjûn yn de folgjende tabel.

    Besit
    Noat

    DETERMINISTYK = WAAR
    Moat eksplisyt ferklearre wurde as in attribút fan de Microsoft .NET Framework-metoade.

    PRECISE = TRUE
    Moat eksplisyt ferklearre wurde as in attribút fan 'e .NET Framework-metoade.

    DATA ACCESS = GEEN SQL
    Bepaald troch it ynstellen fan DataAccess-attribút op DataAccessKind.None en SystemDataAccess-attribút op SystemDataAccessKind.None.

    EKSTERNE TAEGANG = NEE
    Dizze eigenskip stiet standert op NO foar CLR-routines.

  • De werjefte moat makke wurde mei de WITH SCHEMABINDING opsje.
  • De werjefte moat allinich basistabellen ferwize dy't yn deselde databank binne as de werjefte. De werjefte kin net ferwize nei oare werjeften.
  • De SELECT-útspraak yn 'e werjeftedefinysje moat de folgjende Transact-SQL-eleminten net befetsje:

    COUNT
    ROWSET funksjes (OPENDATASOURCE, OPENQUERY, OPENROWSET, EN OPENXML)
    OUTER komt mei (LEFT, RIGHT, of FULL)

    Afgeleide tabel (definiearre troch it opjaan fan in SELECT ferklearring yn 'e FROM klausule)
    Sels meidwaan
    Kolommen oantsjutte troch te brûken SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, of AVG
    Common Table Expression (CTE)

    driuwe1, tekst, ntekst, byld, XML, of filestream pylder
    Subquery
    OVER klausule, dy't ranglist of aggregearre finsterfunksjes omfettet

    Folsleine tekst predikaten (CONTAINS, FREETEXT)
    SUM funksje dy't ferwiist nei in nullbere útdrukking
    ORDER BY

    CLR brûker-definiearre aggregaat funksje
    TOP
    CUBE, ROLLUP, of GROUPING SETS operators

    MIN, MAX
    UNION, EXCEPT, of INTERSECT operators
    TABLESAMPLE

    Tabel fariabelen
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Sparse kolom sets
    Inline (TVF) of multi-statement tabel-wurdearre funksjes (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 De yndeksearre werjefte kin befetsje driuwe pylder; lykwols, sokke kolommen kinne net opnommen wurde yn de klustere yndeks kaai.

  • If GROUP BY oanwêzich is, moat de VIEW-definysje befetsje COUNT_BIG(*) en moat net befetsje HAVING. Dizze GROUP BY beheinings binne allinnich fan tapassing op de yndeksearre werjefte definysje. In query kin in yndeksearre werjefte brûke yn syn útfieringsplan, sels as it dizze net foldocht GROUP BY beheiningen.
  • As de werjefte definysje befettet in GROUP BY clause, de kaai fan de unike klustere yndeks kin ferwize allinne de kolommen oantsjutte yn de GROUP BY klausule.

It is hjir dúdlik dat de Yndianen net belutsen wiene, om't se besletten it te dwaan neffens it skema "wy sille net folle dwaan, mar goed." Dat is, se hawwe mear minen op it fjild, mar har lokaasje is transparanter. It meast teloarstellende is dizze beheining:

De werjefte moat allinich basistabellen ferwize dy't yn deselde databank binne as de werjefte. De werjefte kin net ferwize nei oare werjeften.

Yn ús terminology betsjut dit dat in funksje gjin tagong hat ta in oare materialisearre funksje. Dit snijt alle ideology yn 'e bud.
Ek dizze beheining (en fierder yn 'e tekst) ferminderet de gebrûksgefallen sterk:

De SELECT-útspraak yn 'e werjeftedefinysje moat de folgjende Transact-SQL-eleminten net befetsje:

COUNT
ROWSET funksjes (OPENDATASOURCE, OPENQUERY, OPENROWSET, EN OPENXML)
OUTER komt mei (LEFT, RIGHT, of FULL)

Afgeleide tabel (definiearre troch it opjaan fan in SELECT ferklearring yn 'e FROM klausule)
Sels meidwaan
Kolommen oantsjutte troch te brûken SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARP, of AVG
Common Table Expression (CTE)

driuwe1, tekst, ntekst, byld, XML, of filestream pylder
Subquery
OVER klausule, dy't ranglist of aggregearre finsterfunksjes omfettet

Folsleine tekst predikaten (CONTAINS, FREETEXT)
SUM funksje dy't ferwiist nei in nullbere útdrukking
ORDER BY

CLR brûker-definiearre aggregaat funksje
TOP
CUBE, ROLLUP, of GROUPING SETS operators

MIN, MAX
UNION, EXCEPT, of INTERSECT operators
TABLESAMPLE

Tabel fariabelen
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Sparse kolom sets
Inline (TVF) of multi-statement tabel-wurdearre funksjes (MSTVF)
OFFSET

CHECKSUM_AGG

OUTER JOINS, UNION, ORDER BY en oaren binne ferbean. It soe makliker west hawwe om oan te jaan wat koe wurde brûkt as wat net koe wurde brûkt. De list soe wierskynlik folle koarter wêze.

Om gearfetsje: in enoarme set beheiningen yn elke (lit ús kommersjeel) DBMS vs gjin (mei útsûndering fan ien logysk, net technysk) yn LGPL-technology. It moat lykwols opmurken wurde dat it útfieren fan dit meganisme yn relaasjelogika wat dreger is as yn 'e beskreaune funksjonele logika.

Ymplemintaasje

Hoe't it wurket? PostgreSQL wurdt brûkt as in "firtuele masine". D'r is in kompleks algoritme binnen dat queries bouwt. Hjir boarne. En d'r is net allinich in grutte set heuristyk mei in boskje ifs. Dat, as jo in pear moannen hawwe om te studearjen, kinne jo besykje arsjitektuer te begripen.

Wurket it effektyf? Hiel effektyf. Spitigernôch is dit dreech te bewizen. Ik kin allinich sizze dat as jo de tûzenen fragen beskôgje dy't besteane yn grutte applikaasjes, dan binne se yn trochsneed effisjinter as dy fan in goede ûntwikkelder. In poerbêste SQL-programmeur kin elke fraach effisjinter skriuwe, mar mei tûzen fragen sil hy gewoan net de motivaasje of tiid hawwe om it te dwaan. It iennichste ding dat ik no kin oanhelje as bewiis fan effektiviteit is dat ferskate projekten wurkje oan it platfoarm boud op dizze DBMS ERP systemen, dy't tûzenen ferskillende MATERIALIZED-funksjes hawwe, mei tûzenen brûkers en terabyte-databases mei hûnderten miljoenen records dy't rinne op in gewoane twa-prosessor-tsjinner. Elkenien kin lykwols de effektiviteit kontrolearje / wjerlizze troch te downloaden perron en PostgreSQL, oan dwaan logging SQL queries en besykje te feroarjen de logika en gegevens dêr.

Yn 'e folgjende artikels sil ik ek prate oer hoe't jo beheiningen kinne ynstelle op funksjes, wurkje mei feroaringssesjes, en folle mear.

Boarne: www.habr.com

Add a comment