Balansavimas rašo ir skaito duomenų bazėje

Balansavimas rašo ir skaito duomenų bazėje
Ankstesniame straipsnis Aprašiau duomenų bazės, sukurtos remiantis funkcijomis, o ne lentelėmis ir laukais, kaip reliacinėse duomenų bazėse, koncepciją ir įgyvendinimą. Jame pateikta daug pavyzdžių, parodančių šio požiūrio pranašumus prieš klasikinį. Daugeliui jie atrodė nepakankamai įtikinami.

Šiame straipsnyje parodysiu, kaip ši koncepcija leidžia greitai ir patogiai subalansuoti rašymą ir skaitymą į duomenų bazę, nekeičiant veikimo logikos. Panašias funkcijas buvo bandoma įdiegti šiuolaikinėse komercinėse DBVS (ypač Oracle ir Microsoft SQL Server). Straipsnio pabaigoje parodysiu, kad tai, ką jie padarė, švelniai tariant, nelabai pavyko.

aprašymas

Kaip ir anksčiau, kad geriau suprasčiau, aprašą pradėsiu nuo pavyzdžių. Tarkime, reikia įdiegti logiką, kuri grąžins skyrių sąrašą su juose esančių darbuotojų skaičiumi ir bendrą atlyginimą.

Funkcinėje duomenų bazėje tai atrodytų taip:

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

Šios užklausos vykdymo sudėtingumas bet kurioje DBVS bus lygus O (darbuotojų skaičius)nes atliekant šį skaičiavimą reikia nuskaityti visą darbuotojų lentelę ir sugrupuoti juos pagal skyrius. Priklausomai nuo pasirinkto plano, bus ir nedidelis (manome, kad darbuotojų daug daugiau nei padalinių) priedas O (darbuotojų skaičius žurnale) arba O (padalinių skaičius) grupavimui ir pan.

Akivaizdu, kad vykdymo išlaidos skirtingose ​​DBVS gali skirtis, tačiau sudėtingumas niekaip nepasikeis.

Siūlomame įgyvendinime funkcinė DBVS sugeneruos vieną antrinę užklausą, kuri apskaičiuos reikiamas skyriaus reikšmes, o tada prisijungs prie skyriaus lentelės, kad gautų pavadinimą. Tačiau kiekvienai funkcijai deklaruojant galima nustatyti specialų MATERIALIZUOTA žymeklį. Sistema automatiškai sukurs atitinkamą lauką kiekvienai tokiai funkcijai. Keičiant funkcijos reikšmę, toje pačioje operacijoje pasikeis ir lauko reikšmė. Pasiekus šią funkciją, bus pasiekiamas iš anksto apskaičiuotas laukas.

Ypač jei funkcijoms nustatote MATERIALIZED skaičiuoti darbuotojus и atlyginimasSuma, tada į lentelę su skyrių sąrašu bus įtraukti du laukai, kuriuose bus saugomas darbuotojų skaičius ir bendras jų atlyginimas. Kai pasikeičia darbuotojai, jų atlyginimai ar priklausomybė nuo padalinių, sistema automatiškai pakeis šių laukų reikšmes. Aukščiau pateikta užklausa tiesiogiai pasieks šiuos laukus ir bus vykdoma O (padalinių skaičius).

Kokie yra apribojimai? Tik vienas dalykas: tokia funkcija turi turėti baigtinį skaičių įvesties reikšmių, kurioms jos reikšmė yra apibrėžta. Priešingu atveju bus neįmanoma sukurti lentelės, kurioje būtų saugomos visos jos reikšmės, nes negali būti lentelės su begaliniu eilučių skaičiumi.

Pavyzdys:

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

Ši funkcija apibrėžiama begaliniam skaičiui N reikšmių (pavyzdžiui, tinka bet kokia neigiama reikšmė). Todėl ant jo negalima dėti MATERIALIZED. Taigi tai yra loginis, o ne techninis apribojimas (ty ne todėl, kad negalėjome jo įgyvendinti). Priešingu atveju nėra jokių apribojimų. Galite naudoti grupavimą, rūšiavimą, AND ir ARBA, SKAITINIUS, rekursiją ir kt.

Pavyzdžiui, ankstesnio straipsnio 2.2 užduotyje abiem funkcijoms galite įdėti MATERIALIZED:

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;

Pati sistema sukurs vieną lentelę su tipo klavišais Klientas, Produktas и INTEGERIS, pridės du laukus ir atnaujins juose esančias laukų reikšmes su bet kokiais pakeitimais. Iškvietus šias funkcijas, jos nebus skaičiuojamos, o reikšmės bus nuskaitomos iš atitinkamų laukų.

Naudodami šį mechanizmą galite, pavyzdžiui, atsikratyti rekursijų (CTE) užklausose. Visų pirma apsvarstykite grupes, kurios sudaro medį, naudodamos vaiko ir tėvų ryšį (kiekviena grupė turi nuorodą į savo tėvą):

parent = DATA Group (Group);

Funkcinėje duomenų bazėje rekursijos logika gali būti nurodyta taip:

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;

Kadangi už funkciją isParent yra pažymėta MATERIALIZUOTA, tada jam bus sukurta lentelė su dviem raktais (grupėmis), kurioje laukelis isParent bus teisinga tik tuo atveju, jei pirmasis raktas yra antrojo raktas. Įrašų skaičius šioje lentelėje bus lygus grupių skaičiui, padaugintam iš vidutinio medžio gylio. Jei jums reikia, pavyzdžiui, suskaičiuoti tam tikros grupės palikuonių skaičių, galite naudoti šią funkciją:

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

SQL užklausoje CTE nebus. Vietoj to bus paprasta GROUP BY.

Naudodami šį mechanizmą taip pat galite lengvai denormalizuoti duomenų bazę, jei reikia:

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

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

Iškviečiant funkciją duomenys užsakymo eilutei laukas, kuriam yra indeksas, bus nuskaitytas iš lentelės su užsakymo eilutėmis. Pasikeitus užsakymo datai, pati sistema automatiškai perskaičiuos denormalizuotą datą eilutėje.

privalumai

Kam skirtas visas šis mechanizmas? Klasikinėse DBVS, neperrašydamas užklausų, kūrėjas arba DBA gali keisti tik indeksus, nustatyti statistiką ir nurodyti užklausų planuotojui, kaip juos vykdyti (o PATARIMAI galimi tik komercinėse DBVS). Kad ir kaip jie stengtųsi, jie negalės užpildyti pirmosios straipsnio užklausos O (padalinių skaičius) nekeičiant užklausų ir nepridedant aktyviklių. Siūlomoje schemoje kūrimo etape nereikia galvoti apie duomenų saugojimo struktūrą ir kokias agregacijas naudoti. Visa tai galima nesunkiai pakeisti skrendant, tiesiogiai veikiant.

Praktikoje tai atrodo taip. Kai kurie žmonės logiką kuria tiesiogiai pagal atliekamą užduotį. Jie nesupranta nei algoritmų, nei jų sudėtingumo, nei vykdymo planų, nei sujungimų tipų, nei kitų techninių komponentų. Šie žmonės yra labiau verslo analitikai nei kūrėjai. Tada visa tai pereina į bandymus arba eksploataciją. Įgalina ilgai vykdomų užklausų registravimą. Kai aptinkama ilga užklausa, kiti žmonės (daugiau techniniai – iš esmės DBA) nusprendžia įjungti MATERIALIZED tam tikroje tarpinėje funkcijoje. Tai šiek tiek sulėtina įrašymą (nes reikia atnaujinti papildomą operacijos lauką). Tačiau žymiai pagreitėja ne tik ši užklausa, bet ir visos kitos, kurios naudoja šią funkciją. Tuo pačiu metu gana lengva nuspręsti, kurią funkciją įgyvendinti. Du pagrindiniai parametrai: galimų įvesties reikšmių skaičius (tiek įrašų bus atitinkamoje lentelėje) ir kaip dažnai jis naudojamas kitose funkcijose.

Analogai

Šiuolaikinės komercinės DBVS turi panašius mechanizmus: MATERIALIZED VIEW su FAST REFRESH (Oracle) ir INDEXED VIEW (Microsoft SQL Server). PostgreSQL sistemoje MATERIALIZED VIEW negali būti atnaujintas per operaciją, o tik paprašius (ir net su labai griežtais apribojimais), todėl mes to nesvarstome. Tačiau jie turi keletą problemų, kurios žymiai riboja jų naudojimą.

Pirma, materializavimą galite įjungti tik tuo atveju, jei jau sukūrėte įprastą VIEW. Priešingu atveju turėsite perrašyti likusias užklausas, kad galėtumėte pasiekti naujai sukurtą rodinį, kad galėtumėte naudoti šį materializavimą. Arba palikite viską kaip yra, bet bus bent jau neefektyvu, jei bus tam tikri jau iš anksto paskaičiuoti duomenys, bet daugelis užklausų ne visada jais pasinaudoja, o perskaičiuoja.

Antra, jie turi daugybę apribojimų:

orakulas

5.3.8.4 Bendrieji greito atnaujinimo apribojimai

Materializuoto rodinio apibrėžianti užklausa ribojama taip:

  • Materializuotame rodinyje neturi būti nuorodų į nesikartojančius posakius, pvz SYSDATE ir ROWNUM.
  • Materializuotame rodinyje neturi būti nuorodų į RAW or LONG RAW duomenų tipai.
  • Jame negali būti a SELECT sąrašo antrinė užklausa.
  • Jame negali būti analitinių funkcijų (pvz., RANK) viduje SELECT sąlyga.
  • Jis negali nurodyti lentelės, kurioje an XMLIndex indeksas yra apibrėžtas.
  • Jame negali būti a MODEL sąlyga.
  • Jame negali būti a HAVING sąlyga su papildoma užklausa.
  • Jame negali būti įdėtųjų užklausų, kurios turi ANY, ALLarba NOT EXISTS.
  • Jame negali būti a [START WITH …] CONNECT BY sąlyga.
  • Jame negali būti kelių išsamios informacijos lentelių skirtingose ​​svetainėse.
  • ON COMMIT materializuotuose rodiniuose negali būti nuotolinių detalių lentelių.
  • Įdėtuose materializuotuose rodiniuose turi būti sujungimas arba apibendrinimas.
  • Materializuoti sujungimo rodiniai ir materializuoti bendri rodiniai su a GROUP BY sąlyga negali pasirinkti iš indeksu sutvarkytos lentelės.

5.3.8.5 Greito atnaujinimo apribojimai materializuotose peržiūrose tik su prisijungimais

Apibrėžiant materializuotų rodinių užklausas tik su sujungimais ir be agregatų, taikomi šie greito atnaujinimo apribojimai:

  • Visi apribojimai nuo «Bendrieji greito atnaujinimo apribojimai"
  • Jie negali turėti GROUP BY sąlygos arba suvestiniai rodikliai.
  • Visų lentelių eilutės FROM sąrašas turi būti rodomas SELECT užklausos sąrašas.
  • Materializuoti rodinio žurnalai turi būti su eilėmis visose pagrindinėse lentelėse FROM užklausos sąrašas.
  • Negalite sukurti greitai atnaujinamo materializuoto rodinio iš kelių lentelių su paprastais sujungimais, kuriuose yra objekto tipo stulpelis. SELECT pareiškimas.

Be to, jūsų pasirinktas atnaujinimo metodas nebus optimaliai efektyvus, jei:

  • Apibrėžiamojoje užklausoje naudojamas išorinis sujungimas, kuris veikia kaip vidinis sujungimas. Jei apibrėžiančioje užklausoje yra toks sujungimas, apsvarstykite galimybę perrašyti apibrėžiančią užklausą, kad būtų įtrauktas vidinis sujungimas.
  • Šios SELECT materializuoto rodinio sąraše yra išraiškų stulpeliuose iš kelių lentelių.

5.3.8.6 Greito atnaujinimo apribojimai materializuotose rodiniuose su agregatais

Apibrėžiant materializuotų rodinių su agregatais arba sujungimais užklausas, taikomi šie greito atnaujinimo apribojimai:

Greitas atnaujinimas palaikomas abiem ON COMMIT ir ON DEMAND materializuotos nuomonės, tačiau taikomi šie apribojimai:

  • Visos materializuoto rodinio lentelės turi turėti materializuoto rodinio žurnalus, o materializuotų rodinių žurnalai turi:
    • Įtraukti visus stulpelius iš lentelės, nurodytos materializuotame rodinyje.
    • Nurodykite su ROWID ir INCLUDING NEW VALUES.
    • nurodyti SEQUENCE sąlyga, jei tikimasi, kad lentelėje bus įterpimų / tiesioginių įkėlimų, ištrynimų ir atnaujinimų derinys.

  • Tik SUM, COUNT, AVG, STDDEV, VARIANCE, MIN ir MAX palaikomos greitam atnaujinimui.
  • COUNT(*) turi būti nurodyta.
  • Suvestinės funkcijos turi būti tik kaip tolimiausia išraiškos dalis. Tai yra, agregatai, tokie kaip AVG(AVG(x)) or AVG(x)+ AVG(x) neleidžiama.
  • Kiekvienam agregatui, pvz AVG(expr), atitinkamas COUNT(expr) turi būti. „Oracle“ tai rekomenduoja SUM(expr) būti nurodyta.
  • If VARIANCE(expr) or STDDEV(expr) yra nurodyta, COUNT(expr) ir SUM(expr) turi būti nurodyta. „Oracle“ tai rekomenduoja SUM(expr *expr) būti nurodyta.
  • Šios SELECT stulpelis apibrėžiančioje užklausoje negali būti sudėtinga išraiška su stulpeliais iš kelių bazinių lentelių. Galimas sprendimas yra naudoti įdėtą materializuotą rodinį.
  • Šios SELECT sąraše turi būti viskas GROUP BY stulpeliai.
  • Materializuotas vaizdas nėra pagrįstas viena ar daugiau nuotolinių lentelių.
  • Jei naudojate a CHAR duomenų tipas materializuoto rodinio žurnalo filtrų stulpeliuose, pagrindinės svetainės ir materializuoto rodinio simbolių rinkiniai turi būti vienodi.
  • Jei materializuotame rodinyje yra vienas iš toliau nurodytų parametrų, greitas atnaujinimas palaikomas tik naudojant įprastus DML įterpimus ir tiesioginius įkėlimus.
    • Materializuoti vaizdai su MIN or MAX užpildai
    • Materializuoti vaizdai, kurie turi SUM(expr) bet ne COUNT(expr)
    • Materializuoti vaizdai be COUNT(*)

    Toks materializuotas vaizdas vadinamas tik įterptu materializuotu vaizdu.

  • Materializuotas vaizdas su MAX or MIN yra greitai atnaujinamas ištrynus arba sumaišius DML sakinius, jei neturi a WHERE sąlyga.
    Maksimalus per minutę greitas atnaujinimas po ištrynimo arba mišraus DML veikia kitaip, kaip tik įterpimo atveju. Jis ištrina ir iš naujo apskaičiuoja paveiktų grupių maks./min. vertes. Turite žinoti jo poveikį našumui.
  • Materializuoti rodiniai su pavadintais rodiniais arba antrinėmis užklausomis FROM sąlyga gali būti greitai atnaujinta, jei rodiniai gali būti visiškai sujungti. Norėdami sužinoti, kurie rodiniai bus sujungti, žr Oracle Database SQL kalbos nuoroda.
  • Jei nėra išorinių sujungimų, gali būti savavališkai pasirinkti ir sujungti WHERE sąlyga.
  • Materializuoti suvestiniai rodiniai su išorinėmis jungtimis yra greitai atnaujinami po įprastinių DML ir tiesioginių įkėlimų, jei buvo pakeista tik išorinė lentelė. Be to, vidinės sujungimo lentelės sujungimo stulpeliuose turi būti unikalių apribojimų. Jei yra išorinių jungčių, visos jungtys turi būti sujungtos ANDs ir turi naudoti lygybę (=) operatorius.
  • Už materializuotus vaizdus su CUBE, ROLLUP, grupavimo rinkinius arba jų sujungimą, taikomi šie apribojimai:
    • Šios SELECT sąraše turi būti grupavimo žymuo, kuris gali būti a GROUPING_ID veikia visuose GROUP BY išraiškos arba GROUPING atlieka po vieną kiekvienam GROUP BY išraiška. Pavyzdžiui, jei GROUP BY materializuoto požiūrio sąlyga yra "GROUP BY CUBE(a, b)", tada SELECT sąraše turi būti arba "GROUPING_ID(a, b)» arba «GROUPING(a) AND GROUPING(b)» kad materializuotas vaizdas būtų greitai atnaujinamas.
    • GROUP BY neturėtų atsirasti pasikartojančių grupių. Pavyzdžiui, "GROUP BY a, ROLLUP(a, b)" nėra greitai atnaujinamas, nes dėl to susidaro pasikartojančios grupės"(a), (a, b), AND (a)"

5.3.8.7 Greito atnaujinimo apribojimai materializuotose peržiūrose naudojant UNION ALL

Materializuoti vaizdai su UNION ALL nustatyti operatoriaus palaikymą REFRESH FAST galimybė, jei tenkinamos šios sąlygos:

  • Apibrėžiamojoje užklausoje turi būti UNION ALL aukščiausio lygio operatorius.

    Šios UNION ALL operatorius negali būti įterptas į antrinę užklausą, išskyrus vieną išimtį: The UNION ALL gali būti antrinėje užklausoje FROM sąlyga, jei apibrėžianti užklausa yra tokios formos SELECT * FROM (peržiūrėkite arba pateikite antrinę užklausą naudodami UNION ALL), kaip parodyta šiame pavyzdyje:

    KURTI PERŽIŪRĄ view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM CHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM klientai c WHERE c.cust_last „Jonesas“); KURTI MATERIALIZUOTĄ RODINĮ unionall_inside_view_mv GREITAI ATNAUJINTI PRAŠYMAS AS SELECT * FROM view_with_unionall;
    

    Atkreipkite dėmesį, kad vaizdas view_with_unionall atitinka greito atnaujinimo reikalavimus.

  • Kiekvienas užklausų blokas UNION ALL užklausa turi atitikti greitai atnaujinamo materializuoto rodinio su agregatais arba greitai atnaujinamo materializuoto rodinio su sujungimais reikalavimus.

    Atitinkami materializuoto rodinio žurnalai turi būti sukurti lentelėse, kaip reikalaujama atitinkamo tipo greitai atnaujinamam materializuoto rodinio tipui.
    Atminkite, kad „Oracle“ duomenų bazė taip pat leidžia naudoti specialų vienos lentelės materializuoto rodinio atvejį su sujungimais, tik jei ROWID stulpelis buvo įtrauktas į SELECT sąraše ir materializuoto rodinio žurnale. Tai rodoma apibrėžiančioje rodinio užklausoje view_with_unionall.

  • Šios SELECT kiekvienos užklausos sąraše turi būti a UNION ALL žymeklis ir UNION ALL Kiekviename stulpelyje turi būti atskira pastovi skaitinė arba eilutės reikšmė UNION ALL šaka. Be to, žymeklio stulpelis turi būti toje pačioje eilės padėtyje SELECT kiekvieno užklausų bloko sąrašas. Matyti "UNION ALL Žymeklis ir užklausa perrašyti» Norėdami gauti daugiau informacijos apie UNION ALL žymekliai.
  • Kai kurios funkcijos, pvz., išoriniai sujungimai, tik įterpiamos sukauptos materializuotų rodinių užklausos ir nuotolinės lentelės, nepalaikomos materializuotuose rodiniuose su UNION ALL. Tačiau atminkite, kad replikacijoje naudojami materializuoti rodiniai, kuriuose nėra sujungimų ar agregatų, gali būti greitai atnaujinami, kai UNION ALL arba naudojami nuotoliniai stalai.
  • Suderinamumo inicijavimo parametras turi būti nustatytas kaip 9.2.0 arba didesnis, kad būtų sukurtas greitai atnaujinamas materializuotas vaizdas su UNION ALL.

Nenoriu įžeisti Oracle gerbėjų, bet sprendžiant iš jų apribojimų sąrašo, atrodo, kad šis mechanizmas buvo parašytas ne bendru atveju, naudojant kažkokį modelį, o tūkstančiai indų, kur kiekvienam buvo suteikta galimybė parašyti savo šaką, ir kiekvienas iš jų padarė ką galėjo ir padarė. Naudoti šį mechanizmą tikrajai logikai prilygsta vaikščiojimui per minų lauką. Galite gauti miną bet kuriuo metu, paspaudę vieną iš neakivaizdžių apribojimų. Kaip tai veikia, taip pat yra atskiras klausimas, tačiau tai nepatenka į šio straipsnio taikymo sritį.

"Microsoft SQL Server

Papildomi reikalavimai

Be SET parinkčių ir deterministinių funkcijų reikalavimų, turi būti laikomasi šių reikalavimų:

  • Vartotojas, kuris vykdo CREATE INDEX turi būti vaizdo savininkas.
  • Kai kuriate indeksą, IGNORE_DUP_KEY parinktis turi būti nustatyta į IŠJUNGTA (numatytasis nustatymas).
  • Lentelės turi būti nurodytos dviejų dalių pavadinimais, schema.lentelės pavadinimas rodinio apibrėžime.
  • Rodinyje nurodytos vartotojo nustatytos funkcijos turi būti sukurtos naudojant WITH SCHEMABINDING pasirinkimas.
  • Visos vartotojo nustatytos funkcijos, nurodytos rodinyje, turi būti nurodytos dviejų dalių pavadinimais, ..
  • Vartotojo nustatytos funkcijos prieigos prie duomenų ypatybė turi būti NO SQL, o išorinės prieigos savybė turi būti NO.
  • Įprastos kalbos vykdymo laiko (CLR) funkcijos gali būti rodomos rodinio pasirinkimo sąraše, bet negali būti sugrupuoto indekso rakto apibrėžimo dalis. CLR funkcijos negali būti rodomos rodinio WHERE sakinyje arba JOIN operacijos sakinyje ON.
  • CLR funkcijos ir CLR vartotojo apibrėžtų tipų metodai, naudojami rodinio apibrėžime, turi turėti ypatybes, nustatytas taip, kaip parodyta šioje lentelėje.

    Nuosavybė
    pastabos

    DETERMINISTINIS = TRUE
    Turi būti aiškiai nurodytas kaip Microsoft .NET Framework metodo atributas.

    TIKSLU = TRUE
    Turi būti aiškiai nurodytas kaip .NET Framework metodo atributas.

    DUOMENŲ PRIEIGA = NĖRA SQL
    Nustatyta nustatant DataAccess atributą į DataAccessKind.None ir SystemDataAccess atributą į SystemDataAccessKind.None.

    IŠORINĖ PRIEIGA = NE
    Pagal numatytuosius nustatymus ši ypatybė CLR rutinoms yra NE.

  • Rodinys turi būti sukurtas naudojant WITH SCHEMABINDING pasirinkimas.
  • Rodinys turi nurodyti tik bazines lenteles, kurios yra toje pačioje duomenų bazėje kaip ir rodinys. Rodinys negali nurodyti kitų rodinių.
  • Rodinio apibrėžimo sakinyje SELECT negali būti šių Transact-SQL elementų:

    COUNT
    ROWSET funkcijos (OPENDATASOURCE, OPENQUERY, OPENROWSET, IR OPENXML)
    OUTER prisijungia (LEFT, RIGHTarba FULL)

    Išvestinė lentelė (apibrėžta nurodant a SELECT pareiškimas FROM sąlyga)
    Savarankiškai prisijungia
    Stulpelių nurodymas naudojant SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARParba AVG
    Bendroji lentelės išraiška (CTE)

    plaukti1, tekstas, ntekstas, vaizdas, XMLarba failų srautas stulpeliai
    antrinė užklausa
    OVER sąlyga, kuri apima reitingavimo arba agregato lango funkcijas

    Viso teksto predikatai (CONTAINS, FREETEXT)
    SUM funkcija, kuri nurodo į nulinę išraišką
    ORDER BY

    CLR vartotojo apibrėžta agregavimo funkcija
    TOP
    CUBE, ROLLUParba GROUPING SETS Operatoriai

    MIN, MAX
    UNION, EXCEPTarba INTERSECT Operatoriai
    TABLESAMPLE

    Lentelės kintamieji
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Reti stulpelių rinkiniai
    Eilutinės (TVF) arba kelių teiginių lentelės vertės funkcijos (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Indeksuotame rodinyje gali būti plaukti stulpeliai; tačiau tokių stulpelių negalima įtraukti į klasterinio indekso raktą.

  • If GROUP BY yra, apibrėžime VIEW turi būti COUNT_BIG(*) ir neturi būti HAVING, Tai GROUP BY apribojimai taikomi tik indeksuoto rodinio apibrėžimui. Užklausa vykdymo plane gali naudoti indeksuotą rodinį, net jei ji šių reikalavimų neatitinka GROUP BY apribojimai.
  • Jei rodinio apibrėžime yra a GROUP BY sąlygą, unikalaus sugrupuoto indekso raktas gali nurodyti tik nurodytus stulpelius GROUP BY sąlyga.

Čia aišku, kad indai nedalyvavo, nes nusprendė tai padaryti pagal schemą „darom mažai, bet gerai“. Tai yra, jie turi daugiau minų lauke, tačiau jų vieta yra skaidresnė. Labiausiai nuviliantis dalykas yra šis apribojimas:

Rodinys turi nurodyti tik bazines lenteles, kurios yra toje pačioje duomenų bazėje kaip ir rodinys. Rodinys negali nurodyti kitų rodinių.

Mūsų terminologijoje tai reiškia, kad funkcija negali pasiekti kitos materializuotos funkcijos. Tai sumažina visą ideologiją.
Be to, šis apribojimas (ir toliau tekste) labai sumažina naudojimo atvejus:

Rodinio apibrėžimo sakinyje SELECT negali būti šių Transact-SQL elementų:

COUNT
ROWSET funkcijos (OPENDATASOURCE, OPENQUERY, OPENROWSET, IR OPENXML)
OUTER prisijungia (LEFT, RIGHTarba FULL)

Išvestinė lentelė (apibrėžta nurodant a SELECT pareiškimas FROM sąlyga)
Savarankiškai prisijungia
Stulpelių nurodymas naudojant SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARParba AVG
Bendroji lentelės išraiška (CTE)

plaukti1, tekstas, ntekstas, vaizdas, XMLarba failų srautas stulpeliai
antrinė užklausa
OVER sąlyga, kuri apima reitingavimo arba agregato lango funkcijas

Viso teksto predikatai (CONTAINS, FREETEXT)
SUM funkcija, kuri nurodo į nulinę išraišką
ORDER BY

CLR vartotojo apibrėžta agregavimo funkcija
TOP
CUBE, ROLLUParba GROUPING SETS Operatoriai

MIN, MAX
UNION, EXCEPTarba INTERSECT Operatoriai
TABLESAMPLE

Lentelės kintamieji
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Reti stulpelių rinkiniai
Eilutinės (TVF) arba kelių teiginių lentelės vertės funkcijos (MSTVF)
OFFSET

CHECKSUM_AGG

IŠORĖS JUNGTYS, SĄJUNGOS, UŽSAKYMAS ir kiti draudžiami. Galbūt būtų buvę lengviau nurodyti, ką galima naudoti, o ne tai, ko negalima naudoti. Sąrašas tikriausiai būtų daug trumpesnis.

Apibendrinant: didžiulis apribojimų rinkinys kiekvienoje (pažymime komercinėje) DBVS, palyginti su jokiu (išskyrus vieną loginį, o ne techninį) LGPL technologijoje. Tačiau reikia pažymėti, kad šio mechanizmo įgyvendinimas reliacinėje logikoje yra šiek tiek sunkesnis nei aprašytoje funkcinėje logikoje.

Vykdymas

Kaip tai veikia? PostgreSQL naudojamas kaip „virtuali mašina“. Viduje yra sudėtingas algoritmas, kuris sukuria užklausas. Čia šaltinis. Ir yra ne tik didelis euristikos rinkinys su daugybe if. Taigi, jei turite porą mėnesių studijuoti, galite pabandyti perprasti architektūrą.

Ar tai veikia efektyviai? Gana veiksminga. Deja, tai sunku įrodyti. Galiu tik pasakyti, kad jei atsižvelgsite į tūkstančius užklausų, kurios yra didelėse programose, tada jos vidutiniškai yra efektyvesnės nei gero kūrėjo. Puikus SQL programuotojas gali efektyviau parašyti bet kokią užklausą, tačiau su tūkstančiais užklausų jis tiesiog neturės nei motyvacijos, nei laiko tai padaryti. Vienintelis dalykas, kurį dabar galiu paminėti kaip efektyvumo įrodymą, yra tai, kad keli projektai veikia platformoje, sukurtoje ant šios DBVS. ERP sistemos, kurios turi tūkstančius skirtingų MATERIALIZUOTŲ funkcijų, su tūkstančiais vartotojų ir terabaitų duomenų bazėmis su šimtais milijonų įrašų, veikiančių įprastame dviejų procesorių serveryje. Tačiau kiekvienas gali patikrinti / paneigti veiksmingumą atsisiųsdamas platforma ir PostgreSQL, įjungtas registruodami SQL užklausas ir bandydami pakeisti ten esančią logiką bei duomenis.

Tolesniuose straipsniuose taip pat kalbėsiu apie tai, kaip galite nustatyti funkcijų apribojimus, dirbti su keitimo seansais ir dar daugiau.

Šaltinis: www.habr.com

Добавить комментарий