Balancimi shkruan dhe lexon në një bazë të dhënash

Balancimi shkruan dhe lexon në një bazë të dhënash
Në të mëparshmen artikull Përshkrova konceptin dhe zbatimin e një baze të dhënash të ndërtuar mbi bazën e funksioneve, në vend të tabelave dhe fushave si në bazat e të dhënave relacionale. Ai dha shumë shembuj që tregojnë avantazhet e kësaj qasjeje mbi atë klasike. Shumë i panë ato jo mjaftueshëm bindëse.

Në këtë artikull, unë do të tregoj se si ky koncept ju lejon të balanconi shpejt dhe me lehtësi shkrimet dhe leximet në bazën e të dhënave pa ndonjë ndryshim në logjikën e funksionimit. Funksionalitet i ngjashëm është tentuar të zbatohet në DBMS moderne komerciale (në veçanti, Oracle dhe Microsoft SQL Server). Në fund të artikullit do të tregoj se ajo që ata bënë, për ta thënë butë, nuk funksionoi shumë mirë.

Përshkrim

Si më parë, për ta kuptuar më mirë do ta nis përshkrimin me shembuj. Le të themi se duhet të zbatojmë logjikën që do të kthejë një listë të departamenteve me numrin e punonjësve në to dhe pagën totale të tyre.

Në një bazë të dhënash funksionale do të duket kështu:

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

Kompleksiteti i ekzekutimit të këtij pyetësori në çdo DBMS do të jetë i barabartë me O (numri i punonjësve)sepse kjo llogaritje kërkon skanimin e të gjithë tabelës së punonjësve dhe më pas grupimin e tyre sipas departamenteve. Do të ketë gjithashtu një shtesë të vogël (ne besojmë se ka shumë më shumë punonjës sesa departamente) në varësi të planit të zgjedhur O (regjistri i numrit të punonjësve) ose O (numri i departamenteve) për grupim e kështu me radhë.

Është e qartë se shpenzimet e përgjithshme të ekzekutimit mund të jenë të ndryshme në DBMS të ndryshme, por kompleksiteti nuk do të ndryshojë në asnjë mënyrë.

Në zbatimin e propozuar, DBMS funksionale do të gjenerojë një nënpyetje që do të llogarisë vlerat e kërkuara për departamentin dhe më pas do të bëjë një JOIN me tabelën e departamentit për të marrë emrin. Megjithatë, për çdo funksion, kur deklarohet, është e mundur të vendoset një shënues i veçantë i MATERIALIZUAR. Sistemi do të krijojë automatikisht një fushë përkatëse për secilin funksion të tillë. Kur ndryshoni vlerën e një funksioni, vlera e fushës do të ndryshojë gjithashtu në të njëjtin transaksion. Kur qaseni në këtë funksion, do të aksesohet fusha e parallogaritur.

Në veçanti, nëse vendosni MATERIALIZED për funksionet countPunonjësit и paga Shuma, më pas në tabelën me listën e departamenteve do të shtohen dy fusha, ku do të ruhet numri i punonjësve dhe paga totale e tyre. Sa herë që ka një ndryshim në punonjësit, pagat e tyre ose përkatësitë e departamenteve, sistemi do të ndryshojë automatikisht vlerat e këtyre fushave. Kërkesa e mësipërme do të hyjë drejtpërdrejt në këto fusha dhe do të ekzekutohet në O (numri i departamenteve).

Cilat janë kufizimet? Vetëm një gjë: një funksion i tillë duhet të ketë një numër të kufizuar vlerash hyrëse për të cilat përcaktohet vlera e tij. Përndryshe, do të jetë e pamundur të ndërtohet një tabelë që ruan të gjitha vlerat e saj, pasi nuk mund të ketë një tabelë me një numër të pafund rreshtash.

Shembull:

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

Ky funksion është përcaktuar për një numër të pafund vlerash të N (për shembull, çdo vlerë negative është e përshtatshme). Prandaj, nuk mund të vendosni MATERIALIZUAR mbi të. Pra, ky është një kufizim logjik, jo teknik (d.m.th., jo sepse nuk mund ta zbatonim). Përndryshe, nuk ka kufizime. Mund të përdorni grupime, renditje, DHE dhe OSE, Ndarje, rekursion, etj.

Për shembull, në problemin 2.2 të artikullit të mëparshëm, mund të vendosni MATERIALIZED në të dy funksionet:

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;

Vetë sistemi do të krijojë një tabelë me çelësat e tipit Klient, Produkt и INTEGERI, do t'i shtojë dy fusha dhe do të përditësojë vlerat e fushave në to me çdo ndryshim. Kur të bëhen thirrje të mëtejshme për këto funksione, ato nuk do të llogariten, por vlerat do të lexohen nga fushat përkatëse.

Duke përdorur këtë mekanizëm, ju, për shembull, mund të hiqni qafe rekursionet (CTE) në pyetje. Në veçanti, merrni parasysh grupet që formojnë një pemë duke përdorur marrëdhënien fëmijë/prind (çdo grup ka një lidhje me prindin e tij):

parent = DATA Group (Group);

Në një bazë të dhënash funksionale, logjika e rekursionit mund të specifikohet si më poshtë:

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;

Që për funksionin është Prindër shënohet MATERIALIZUAR, atëherë për të do të krijohet një tabelë me dy çelësa (grupe), në të cilën fusha është Prindër do të jetë e vërtetë vetëm nëse çelësi i parë është fëmijë i të dytit. Numri i hyrjeve në këtë tabelë do të jetë i barabartë me numrin e grupeve të shumëzuar me thellësinë mesatare të pemës. Nëse keni nevojë, për shembull, të numëroni numrin e pasardhësve të një grupi të caktuar, mund të përdorni këtë funksion:

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

Nuk do të ketë CTE në pyetjen SQL. Në vend të kësaj do të ketë një GROUP BY të thjeshtë.

Duke përdorur këtë mekanizëm, ju gjithashtu mund të çnormalizoni me lehtësi bazën e të dhënave nëse është e nevojshme:

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

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

Kur thërrisni një funksion data për rreshtin e porosisë, fusha për të cilën ka indeks do të lexohet nga tabela me rreshtat e rendit. Kur ndryshon data e porosisë, vetë sistemi do të rillogarisë automatikisht datën e denormalizuar në linjë.

Avantazhet

Për çfarë shërben i gjithë ky mekanizëm? Në DBMS-të klasike, pa rishkrimin e pyetjeve, një zhvillues ose DBA mund të ndryshojë vetëm indekset, të përcaktojë statistikat dhe t'i tregojë planifikuesit të pyetjeve se si t'i ekzekutojë ato (dhe HINT-të disponohen vetëm në DBMS-të komerciale). Pavarësisht se sa shumë përpiqen, ata nuk do të jenë në gjendje të plotësojnë pyetjen e parë në artikullin në O (numri i departamenteve) pa ndryshuar pyetjet ose pa shtuar nxitës. Në skemën e propozuar, në fazën e zhvillimit nuk duhet të mendoni për strukturën e ruajtjes së të dhënave dhe cilat grumbullime të përdorni. E gjithë kjo mund të ndryshohet lehtësisht në fluturim, drejtpërdrejt në funksion.

Në praktikë duket kështu. Disa njerëz zhvillojnë logjikën drejtpërdrejt bazuar në detyrën në fjalë. Ata nuk i kuptojnë algoritmet dhe kompleksitetin e tyre, as planet e ekzekutimit, as llojet e lidhjeve, as ndonjë komponent tjetër teknik. Këta njerëz janë më shumë analistë biznesi sesa zhvillues. Pastaj, e gjithë kjo kalon në testim ose funksionim. Mundëson regjistrimin e pyetjeve të gjata. Kur zbulohet një pyetje e gjatë, atëherë njerëz të tjerë (më teknikë - në thelb DBA) vendosin të aktivizojnë MATERIALIZED në një funksion të ndërmjetëm. Kjo ngadalëson pak regjistrimin (pasi kërkon përditësimin e një fushe shtesë në transaksion). Megjithatë, jo vetëm kjo pyetje është përshpejtuar ndjeshëm, por edhe të gjithë të tjerët që përdorin këtë funksion. Në të njëjtën kohë, vendosja se cili funksion të materializohet është relativisht i lehtë. Dy parametra kryesorë: numri i vlerave të mundshme hyrëse (kjo është sa regjistrime do të jenë në tabelën përkatëse) dhe sa shpesh përdoret në funksione të tjera.

analoge

DBMS-të moderne komerciale kanë mekanizma të ngjashëm: PAMJE E MATERIALIZUAR me REFRESHIM TË FAST (Oracle) dhe PAMJE E INDEXED (Microsoft SQL Server). Në PostgreSQL, PAMJA E MATERIALIZUAR nuk mund të përditësohet në një transaksion, por vetëm sipas kërkesës (dhe madje edhe me kufizime shumë të rrepta), kështu që ne nuk e konsiderojmë atë. Por ata kanë disa probleme që kufizojnë ndjeshëm përdorimin e tyre.

Së pari, mund të aktivizoni materializimin vetëm nëse keni krijuar tashmë një VIEW të rregullt. Përndryshe, do t'ju duhet të rishkruani kërkesat e mbetura për të hyrë në pamjen e krijuar rishtazi për të përdorur këtë materializim. Ose lini gjithçka ashtu siç është, por do të jetë të paktën joefektive nëse ka të dhëna tashmë të parallogaritura, por shumë pyetje jo gjithmonë i përdorin ato, por i rillogaritin.

Së dyti, ata kanë një numër të madh kufizimesh:

Orakull

5.3.8.4 Kufizimet e përgjithshme për rifreskimin e shpejtë

Pyetja përcaktuese e pamjes së materializuar kufizohet si më poshtë:

  • Pamja e materializuar nuk duhet të përmbajë referenca ndaj shprehjeve që nuk përsëriten si p.sh SYSDATE ROWNUM.
  • Pamja e materializuar nuk duhet të përmbajë referenca për RAW or LONG RAW llojet e të dhënave.
  • Nuk mund të përmbajë a SELECT nënpyetja e listës.
  • Nuk mund të përmbajë funksione analitike (për shembull, RANK) Në SELECT klauzolë.
  • Nuk mund t'i referohet një tabelë në të cilën një XMLIndex është përcaktuar indeksi.
  • Nuk mund të përmbajë a MODEL klauzolë.
  • Nuk mund të përmbajë a HAVING klauzolë me një nënpyetje.
  • Nuk mund të përmbajë pyetje të mbivendosura që kanë ANY, ALLose NOT EXISTS.
  • Nuk mund të përmbajë a [START WITH …] CONNECT BY klauzolë.
  • Nuk mund të përmbajë tabela të shumta detajesh në sajte të ndryshme.
  • ON COMMIT pamjet e materializuara nuk mund të kenë tabela detajesh të largëta.
  • Pamjet e materializuara të mbivendosura duhet të kenë një bashkim ose agregat.
  • Pikëpamjet e bashkuara të materializuara dhe pamjet agregate të materializuara me a GROUP BY klauzola nuk mund të zgjedhë nga një tabelë e organizuar me indeks.

5.3.8.5 Kufizimet në rifreskimin e shpejtë në pamjet e materializuara vetëm me bashkime

Përcaktimi i pyetjeve për pamjet e materializuara vetëm me bashkime dhe pa agregate kanë kufizimet e mëposhtme për rifreskimin e shpejtë:

  • Të gjitha kufizimet nga «Kufizime të përgjithshme për rifreskimin e shpejtë".
  • Ata nuk mund të kenë GROUP BY klauzola ose agregate.
  • Rreshtat e të gjitha tabelave në FROM lista duhet të shfaqet në SELECT lista e pyetjes.
  • Regjistrat e pamjeve të materializuara duhet të ekzistojnë me rreshta për të gjitha tabelat bazë në FROM lista e pyetjes.
  • Ju nuk mund të krijoni një pamje të materializuar të rifreskueshme të shpejtë nga tabela të shumta me bashkime të thjeshta që përfshijnë një kolonë të llojit të objektit në SELECT deklaratë.

Gjithashtu, metoda e rifreskimit që zgjidhni nuk do të jetë në mënyrë optimale efikase nëse:

  • Pyetja përcaktuese përdor një bashkim të jashtëm që sillet si një bashkim i brendshëm. Nëse pyetja përcaktuese përmban një bashkim të tillë, merrni parasysh rishkrimin e pyetjes përcaktuese që të përmbajë një bashkim të brendshëm.
  • La SELECT lista e pamjes së materializuar përmban shprehje në kolona nga tabela të shumta.

5.3.8.6 Kufizimet në rifreskimin e shpejtë në pamjet e materializuara me agregate

Përcaktimi i pyetjeve për pamjet e materializuara me agregate ose bashkime kanë kufizimet e mëposhtme për rifreskimin e shpejtë:

Rifreskimi i shpejtë mbështetet për të dyja ON COMMIT ON DEMAND pikëpamjet e materializuara, megjithatë zbatohen kufizimet e mëposhtme:

  • Të gjitha tabelat në pamjen e materializuar duhet të kenë regjistra të pamjeve të materializuara dhe regjistrat e pamjeve të materializuara duhet:
    • Përmbani të gjitha kolonat nga tabela e referuar në pamjen e materializuar.
    • Specifikoni me ROWID INCLUDING NEW VALUES.
    • specifikojë SEQUENCE klauzolë nëse tabela pritet të ketë një përzierje të futjeve/ngarkimeve direkte, fshirjeve dhe përditësimeve.

  • Vetëm SUM, COUNT, AVG, STDDEV, VARIANCE, MIN MAX mbështeten për rifreskim të shpejtë.
  • COUNT(*) duhet të specifikohet.
  • Funksionet agregate duhet të shfaqen vetëm si pjesa më e jashtme e shprehjes. Domethënë agregatet si p.sh AVG(AVG(x)) or AVG(x)+ AVG(x) nuk lejohen.
  • Për çdo agregat si p.sh AVG(expr), përkatëse COUNT(expr) duhet të jetë i pranishëm. Oracle e rekomandon atë SUM(expr) të specifikohet.
  • If VARIANCE(expr) or STDDEV(expr) është specifikuar, COUNT(expr) SUM(expr) duhet të specifikohet. Oracle e rekomandon atë SUM(expr *expr) të specifikohet.
  • La SELECT kolona në pyetjen përcaktuese nuk mund të jetë një shprehje komplekse me kolona nga tabela të shumta bazë. Një zgjidhje e mundshme për këtë është përdorimi i një pamje të materializuar të mbivendosur.
  • La SELECT lista duhet të përmbajë të gjitha GROUP BY kolonat.
  • Pamja e materializuar nuk bazohet në një ose më shumë tabela të largëta.
  • Nëse përdorni një CHAR lloji i të dhënave në kolonat e filtrit të një regjistri të pamjes së materializuar, grupet e karaktereve të faqes kryesore dhe pamjes së materializuar duhet të jenë të njëjta.
  • Nëse pamja e materializuar ka një nga të mëposhtmet, atëherë rifreskimi i shpejtë mbështetet vetëm në futjet konvencionale DML dhe ngarkesat direkte.
    • Pikëpamjet e materializuara me MIN or MAX agregatet
    • Pikëpamjet e materializuara të cilat kanë SUM(expr) por jo COUNT(expr)
    • Pamje të materializuara pa COUNT(*)

    Një pamje e tillë e materializuar quhet pamje e materializuar vetëm me insert.

  • Një pamje e materializuar me MAX or MIN rifreskohet shpejt pas fshirjes ose përzierjes së deklaratave DML nëse nuk ka a WHERE klauzolë.
    Rifreskimi i shpejtë maksimal/min pas fshirjes ose DML-së së përzier nuk ka të njëjtën sjellje si rasti vetëm me futje. Fshin dhe rillogarit vlerat maksimale/min për grupet e prekura. Ju duhet të jeni të vetëdijshëm për ndikimin e tij në performancë.
  • Pamje të materializuara me pamje të emërtuara ose nënpyetje në FROM klauzola mund të rifreskohet shpejt me kusht që pamjet të mund të bashkohen plotësisht. Për informacion se cilat pamje do të bashkohen, shihni Referenca gjuhësore e bazës së të dhënave Oracle SQL.
  • Nëse nuk ka lidhje të jashtme, mund të keni zgjedhje arbitrare dhe bashkime në WHERE klauzolë.
  • Pamjet e grumbulluara të materializuara me bashkime të jashtme rifreskohen shpejt pas DML-së konvencionale dhe ngarkesave direkte, me kusht që vetëm tabela e jashtme të jetë modifikuar. Gjithashtu, kufizimet unike duhet të ekzistojnë në kolonat e bashkimit të tabelës së bashkimit të brendshëm. Nëse ka lidhje të jashtme, të gjitha lidhjet duhet të lidhen me ANDs dhe duhet të përdorë barazinë (=) operator.
  • Për pamje të materializuara me CUBE, ROLLUP, grupimi i grupeve ose bashkimi i tyre, zbatohen kufizimet e mëposhtme:
    • La SELECT lista duhet të përmbajë dallues grupimi që mund të jetë ose a GROUPING_ID funksion në të gjitha GROUP BY shprehjet ose GROUPING funksionon një për secilin GROUP BY shprehje. Për shembull, nëse GROUP BY klauzola e pikëpamjes së materializuar është "GROUP BY CUBE(a, b)", pastaj SELECT lista duhet të përmbajë ose "GROUPING_ID(a, b)"ose "GROUPING(a) AND GROUPING(b)» që pamja e materializuar të jetë e rifreskueshme shpejt.
    • GROUP BY nuk duhet të rezultojë në ndonjë grupim të dyfishtë. Për shembull, "GROUP BY a, ROLLUP(a, b)"Nuk rifreskohet shpejt sepse rezulton në grupime të dyfishta"(a), (a, b), AND (a)".

5.3.8.7 Kufizimet në rifreskimin e shpejtë në pamjet e materializuara me UNION ALL

Pikëpamjet e materializuara me UNION ALL vendosur mbështetjen e operatorit REFRESH FAST opsion nëse plotësohen kushtet e mëposhtme:

  • Pyetja përcaktuese duhet të ketë UNION ALL operator në nivelin më të lartë.

    La UNION ALL operatori nuk mund të futet brenda një nënpyetjeje, me një përjashtim: The UNION ALL mund të jetë në një nënpyetje në FROM klauzolë me kusht që pyetja përcaktuese të jetë e formës SELECT * FROM (shiko ose nënpyetje me UNION ALL) si në shembullin e mëposhtëm:

    KRIJO PAMJE view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker NGA klientë c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker NGA klientët c_last c_last c. 'Jones'); KRIJO PAMJE TË MATERIALIZUAR unionall_inside_view_mv RIFIKO SHPEJT ME KËRKESË SI TË ZGJEDHUR * NGA view_with_unionall;
    

    Vini re se pamja view_with_unionall plotëson kërkesat për rifreskim të shpejtë.

  • Çdo bllok pyetësor në UNION ALL pyetja duhet të plotësojë kërkesat e një pamje të materializuar të rifreskueshme të shpejtë me agregate ose një pamje të materializuar me rifreskim të shpejtë me bashkime.

    Regjistrat e duhura të pamjes së materializuar duhet të krijohen në tabela siç kërkohet për llojin përkatës të pamjes së materializuar të rifreskueshme të shpejtë.
    Vini re se baza e të dhënave Oracle gjithashtu lejon rastin e veçantë të një pamjeje të materializuar të tabelës së vetme me bashkime vetëm me kusht ROWID kolona është përfshirë në SELECT listën dhe në regjistrin e pamjes së materializuar. Kjo tregohet në pyetjen përcaktuese të pamjes view_with_unionall.

  • La SELECT lista e çdo pyetje duhet të përfshijë një UNION ALL shënues, dhe UNION ALL kolona duhet të ketë një vlerë konstante numerike ose vargu në secilën prej tyre UNION ALL degë. Më tej, kolona e shënuesit duhet të shfaqet në të njëjtin pozicion rendor në SELECT lista e çdo blloku të pyetjeve. Shiko "UNION ALL Marker dhe Query Rishkruaj» për më shumë informacion në lidhje me UNION ALL shënues.
  • Disa veçori të tilla si bashkimet e jashtme, pyetjet e pamjes së materializuar të materializuar vetëm me futje dhe tabelat në distancë nuk mbështeten për pamjet e materializuara me UNION ALL. Megjithatë, vini re se pamjet e materializuara të përdorura në replikim, të cilat nuk përmbajnë bashkime ose agregate, mund të rifreskohen shpejt kur UNION ALL ose përdoren tabela në distancë.
  • Parametri i inicializimit të përputhshmërisë duhet të vendoset në 9.2.0 ose më lart për të krijuar një pamje të materializuar të rifreskueshme të shpejtë me UNION ALL.

Nuk dua të ofendoj fansat e Oracle, por duke gjykuar nga lista e kufizimeve të tyre, duket se ky mekanizëm është shkruar jo në rastin e përgjithshëm, duke përdorur një lloj modeli, por nga mijëra indianë, ku të gjithëve iu dha mundësia të shkruajnë degën e tyre dhe secili prej tyre bëri atë që mundi dhe bëri. Përdorimi i këtij mekanizmi për logjikën e vërtetë është si të ecësh nëpër një fushë të minuar. Ju mund të merrni një minierë në çdo kohë duke goditur një nga kufizimet jo të dukshme. Si funksionon është gjithashtu një pyetje më vete, por është përtej qëllimit të këtij artikulli.

Microsoft SQL Server

Kërkesa shtesë

Përveç opsioneve SET dhe kërkesave të funksionit përcaktues, duhet të plotësohen kërkesat e mëposhtme:

  • Përdoruesi që ekzekuton CREATE INDEX duhet të jetë pronar i pamjes.
  • Kur krijoni indeksin, IGNORE_DUP_KEY opsioni duhet të vendoset në OFF (cilësimi i paracaktuar).
  • Tabelat duhet të referohen me emra dypjesësh, skemë.emri i tabelës në përkufizimin e pamjes.
  • Funksionet e përcaktuara nga përdoruesi të referuara në pamje duhet të krijohen duke përdorur WITH SCHEMABINDING opsion.
  • Çdo funksion i përcaktuar nga përdoruesi i referuar në pamje duhet të referohet me emra dypjesësh, ..
  • Vetia e aksesit të të dhënave të një funksioni të përcaktuar nga përdoruesi duhet të jetë NO SQL, dhe prona e aksesit të jashtëm duhet të jetë NO.
  • Funksionet e kohës së ekzekutimit të gjuhës së zakonshme (CLR) mund të shfaqen në listën e përzgjedhur të pamjes, por nuk mund të jenë pjesë e përkufizimit të çelësit të indeksit të grupuar. Funksionet CLR nuk mund të shfaqen në klauzolën WHERE të pamjes ose në klauzolën ON të një operacioni JOIN në pamje.
  • Funksionet dhe metodat CLR të llojeve të përcaktuara nga përdoruesi CLR të përdorura në përkufizimin e pamjes duhet të kenë vetitë e vendosura siç tregohet në tabelën e mëposhtme.

    Pronë
    shënim

    DETERMINISTIK = E VËRTETË
    Duhet të deklarohet në mënyrë eksplicite si një atribut i metodës Microsoft .NET Framework.

    SAKTË = E VËRTETË
    Duhet të deklarohet në mënyrë eksplicite si një atribut i metodës .NET Framework.

    QASJA E TË DHËNAVE = PA SQL
    Përcaktohet duke vendosur atributin DataAccess në DataAccessKind.None dhe atributin SystemDataAccess në SystemDataAccessKind.None.

    QASJE E JASHTME = NR
    Kjo veçori vendoset në NO për rutinat CLR.

  • Pamja duhet të krijohet duke përdorur WITH SCHEMABINDING opsion.
  • Pamja duhet t'i referohet vetëm tabelave bazë që janë në të njëjtën bazë të dhënash me pamjen. Pamja nuk mund t'i referohet pikëpamjeve të tjera.
  • Deklarata SELECT në përkufizimin e pamjes nuk duhet të përmbajë elementët e mëposhtëm Transact-SQL:

    COUNT
    Funksionet ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, DHE OPENXML)
    OUTER bashkohet (LEFT, RIGHTose FULL)

    Tabela e prejardhur (përcaktuar duke specifikuar a SELECT deklaratë në FROM klauzolë)
    Vetë-bashkohet
    Specifikimi i kolonave duke përdorur SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARPose AVG
    Shprehja e zakonshme e tabelës (CTE)

    shket1, tekst, ntekst, imazh, XMLose rrjedha e skedarëve kolona
    Subquery
    OVER klauzolë, e cila përfshin renditjen ose funksionet e dritares së përgjithshme

    Kallëzues me tekst të plotë (CONTAINS, FREETEXT)
    SUM funksion që i referohet një shprehjeje të pavlefshme
    ORDER BY

    Funksioni agregat i përcaktuar nga përdoruesi CLR
    TOP
    CUBE, ROLLUPose GROUPING SETS Operatorët

    MIN, MAX
    UNION, EXCEPTose INTERSECT Operatorët
    TABLESAMPLE

    Variablat e tabelës
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Komplete të rralla kolonash
    Funksionet inline (TVF) ose me shumë deklarata me vlerë tabele (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Pamja e indeksuar mund të përmbajë shket kolona; megjithatë, kolona të tilla nuk mund të përfshihen në çelësin e indeksit të grupuar.

  • If GROUP BY është i pranishëm, përkufizimi VIEW duhet të përmbajë COUNT_BIG(*) dhe nuk duhet të përmbajë HAVING. këto GROUP BY kufizimet janë të zbatueshme vetëm për përkufizimin e pamjes së indeksuar. Një pyetje mund të përdorë një pamje të indeksuar në planin e tij të ekzekutimit edhe nëse nuk i plotëson këto GROUP BY kufizime.
  • Nëse përkufizimi i pamjes përmban a GROUP BY klauzolë, çelësi i indeksit unik të grupuar mund t'i referohet vetëm kolonave të specifikuara në GROUP BY klauzolë.

Është e qartë këtu se indianët nuk ishin të përfshirë, pasi ata vendosën ta bëjnë atë sipas skemës "ne do të bëjmë pak, por mirë". Domethënë kanë më shumë mina në fushë, por vendndodhja e tyre është më transparente. Gjëja më zhgënjyese është ky kufizim:

Pamja duhet t'i referohet vetëm tabelave bazë që janë në të njëjtën bazë të dhënash me pamjen. Pamja nuk mund t'i referohet pikëpamjeve të tjera.

Në terminologjinë tonë, kjo do të thotë që një funksion nuk mund të aksesojë një funksion tjetër të materializuar. Kjo shkurton të gjithë ideologjinë në fillim.
Gjithashtu, ky kufizim (dhe më tej në tekst) redukton shumë rastet e përdorimit:

Deklarata SELECT në përkufizimin e pamjes nuk duhet të përmbajë elementët e mëposhtëm Transact-SQL:

COUNT
Funksionet ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, DHE OPENXML)
OUTER bashkohet (LEFT, RIGHTose FULL)

Tabela e prejardhur (përcaktuar duke specifikuar a SELECT deklaratë në FROM klauzolë)
Vetë-bashkohet
Specifikimi i kolonave duke përdorur SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARPose AVG
Shprehja e zakonshme e tabelës (CTE)

shket1, tekst, ntekst, imazh, XMLose rrjedha e skedarëve kolona
Subquery
OVER klauzolë, e cila përfshin renditjen ose funksionet e dritares së përgjithshme

Kallëzues me tekst të plotë (CONTAINS, FREETEXT)
SUM funksion që i referohet një shprehjeje të pavlefshme
ORDER BY

Funksioni agregat i përcaktuar nga përdoruesi CLR
TOP
CUBE, ROLLUPose GROUPING SETS Operatorët

MIN, MAX
UNION, EXCEPTose INTERSECT Operatorët
TABLESAMPLE

Variablat e tabelës
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Komplete të rralla kolonash
Funksionet inline (TVF) ose me shumë deklarata me vlerë tabele (MSTVF)
OFFSET

CHECKSUM_AGG

BASHKIMET E JASHTME, BASHKIMI, ORDER BY dhe të tjera janë të ndaluara. Mund të ishte më e lehtë të specifikohej se çfarë mund të përdorej sesa çfarë nuk mund të përdorej. Lista ndoshta do të ishte shumë më e shkurtër.

Për ta përmbledhur: një grup i madh kufizimesh në çdo (le të kemi parasysh komercial) DBMS kundër asnjë (me përjashtim të një logjike, jo teknike) në teknologjinë LGPL. Megjithatë, duhet theksuar se zbatimi i këtij mekanizmi në logjikën relacionale është disi më i vështirë sesa në logjikën funksionale të përshkruar.

Zbatimi

Si punon? PostgreSQL përdoret si një "makinë virtuale". Ekziston një algoritëm kompleks brenda që ndërton pyetje. Këtu burim. Dhe nuk ka vetëm një grup të madh heuristikash me një mori nëse-sh. Pra, nëse keni nja dy muaj për të studiuar, mund të përpiqeni të kuptoni arkitekturën.

A funksionon në mënyrë efektive? Mjaft efektive. Fatkeqësisht, kjo është e vështirë të vërtetohet. Mund të them vetëm se nëse merrni parasysh mijëra pyetje që ekzistojnë në aplikacione të mëdha, atëherë mesatarisht ato janë më efikase se ato të një zhvilluesi të mirë. Një programues i shkëlqyer SQL mund të shkruajë çdo pyetje në mënyrë më efikase, por me një mijë pyetje ai thjesht nuk do të ketë motivimin ose kohën për ta bërë atë. E vetmja gjë që mund të citoj tani si provë e efektivitetit është se disa projekte po punojnë në platformën e ndërtuar në këtë DBMS Sistemet ERP, të cilat kanë mijëra funksione të ndryshme të MATERIALIZUARA, me mijëra përdorues dhe baza të dhënash terabyte me qindra miliona regjistrime që funksionojnë në një server të rregullt me ​​dy procesorë. Megjithatë, çdokush mund të kontrollojë/të kundërshtojë efektivitetin duke shkarkuar platformë dhe PostgreSQL, ndezur regjistrimi i pyetjeve SQL dhe përpjekje për të ndryshuar logjikën dhe të dhënat atje.

Në artikujt e mëposhtëm, unë do të flas gjithashtu se si mund të vendosni kufizime në funksione, të punoni me sesionet e ndryshimit dhe shumë më tepër.

Burimi: www.habr.com

Shto një koment