Բալանսավորումը գրում և կարդում է տվյալների բազայում

Բալանսավորումը գրում և կարդում է տվյալների բազայում
Նախորդում Հոդված Ես նկարագրեցի տվյալների բազայի հայեցակարգը և իրականացումը, որը կառուցված է ֆունկցիաների հիման վրա, այլ ոչ թե աղյուսակների և դաշտերի, ինչպես հարաբերական տվյալների բազաներում: Այն բերեց բազմաթիվ օրինակներ, որոնք ցույց էին տալիս այս մոտեցման առավելությունները դասականի նկատմամբ: Շատերը գտան, որ դրանք բավականաչափ համոզիչ չեն:

Այս հոդվածում ես ցույց կտամ, թե ինչպես է այս հայեցակարգը թույլ տալիս արագ և հարմար կերպով հավասարակշռել տվյալների բազայի գրերը և ընթերցումները՝ առանց գործառնական տրամաբանության փոփոխության: Նմանատիպ ֆունկցիոնալությունը փորձ է արվել ներդնել ժամանակակից առևտրային DBMS-ներում (մասնավորապես՝ Oracle-ում և Microsoft SQL Server-ում): Հոդվածի վերջում ցույց կտամ, որ նրանց արածը, մեղմ ասած, այնքան էլ լավ չստացվեց։

Նկարագրություն

Ինչպես նախկինում, ավելի լավ հասկանալու համար նկարագրությունը կսկսեմ օրինակներով։ Ենթադրենք, պետք է տրամաբանություն գործադրել, որը կվերադարձնի ստորաբաժանումների ցանկը՝ դրանցում աշխատողների թվով և ընդհանուր աշխատավարձով։

Ֆունկցիոնալ տվյալների բազայում այն ​​կունենա հետևյալ տեսքը.

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

Ցանկացած DBMS-ում այս հարցումը կատարելու բարդությունը համարժեք կլինի O (աշխատողների թիվը)քանի որ այս հաշվարկը պահանջում է սկանավորել աշխատակիցների ամբողջ աղյուսակը և այնուհետև նրանց խմբավորել ըստ բաժինների: Կլինեն նաև փոքր (մենք կարծում ենք, որ աշխատակիցները շատ ավելի շատ են, քան բաժինները) հավելումներ՝ կախված ընտրված պլանից O (աշխատողների թվաքանակը) կամ O (բաժանմունքների թիվը) խմբավորման համար և այլն։

Հասկանալի է, որ կատարման ծախսերը կարող են տարբեր լինել տարբեր DBMS-ներում, բայց բարդությունը ոչ մի կերպ չի փոխվի։

Առաջարկվող իրագործման մեջ ֆունկցիոնալ DBMS-ը կստեղծի մեկ ենթահարկ, որը կհաշվարկի բաժնի համար պահանջվող արժեքները, այնուհետև կկազմի JOIN բաժնի աղյուսակի հետ՝ անունը ստանալու համար: Այնուամենայնիվ, յուրաքանչյուր գործառույթի համար, երբ հայտարարվում է, հնարավոր է սահմանել հատուկ ՆՅՈՒԹԱԿԱՆ մարկեր: Համակարգն ավտոմատ կերպով կստեղծի համապատասխան դաշտ յուրաքանչյուր նման գործառույթի համար: Ֆունկցիայի արժեքը փոխելիս դաշտի արժեքը նույնպես կփոխվի նույն գործարքում: Այս ֆունկցիան մուտք գործելիս մուտք կգործի նախապես հաշվարկված դաշտը:

Մասնավորապես, եթե ֆունկցիաների համար սահմանել եք MATERIALIZED Աշխատակիցներ и աշխատավարձ Գումար, ապա բաժինների ցանկով աղյուսակում կավելացվի երկու դաշտ, որտեղ կպահվեն աշխատողների թիվը և նրանց ընդհանուր աշխատավարձը։ Ամեն անգամ, երբ փոփոխություններ լինեն աշխատակիցների, նրանց աշխատավարձերի կամ գերատեսչությունների պատկանելության մեջ, համակարգը ավտոմատ կերպով կփոխի այս դաշտերի արժեքները: Վերոնշյալ հարցումն ուղղակիորեն կմտնի այս դաշտերը և կկատարվի այնտեղ O (բաժանմունքների թիվը).

Որո՞նք են սահմանափակումները: Միայն մեկ բան. նման գործառույթը պետք է ունենա սահմանափակ թվով մուտքային արժեքներ, որոնց համար սահմանված է դրա արժեքը: Հակառակ դեպքում անհնար կլինի կառուցել աղյուսակ, որը կպահի իր բոլոր արժեքները, քանի որ չի կարող լինել անսահման թվով տողերով աղյուսակ:

Example:

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

Այս ֆունկցիան սահմանված է N-ի անսահման թվով արժեքների համար (օրինակ՝ ցանկացած բացասական արժեք հարմար է): Հետեւաբար, դուք չեք կարող դրա վրա ՆՅՈՒԹԱՑՎԱԾ դնել: Այսպիսով, սա տրամաբանական սահմանափակում է, ոչ թե տեխնիկական (այսինքն, ոչ այն պատճառով, որ մենք չկարողացանք այն իրականացնել): Հակառակ դեպքում սահմանափակումներ չկան։ Դուք կարող եք օգտագործել խմբավորումներ, տեսակավորում, AND և OR, PARTITION, recursion և այլն:

Օրինակ, նախորդ հոդվածի 2.2 խնդրի մեջ կարող եք տեղադրել 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;

Համակարգն ինքնին կստեղծի մեկ աղյուսակ՝ տիպի ստեղներով Հաճախորդ, արդյունք и ԻՆՏԵԳԵՐ, դրան կավելացնի երկու դաշտ և ցանկացած փոփոխությամբ կթարմացնի դրանցում առկա դաշտերի արժեքները։ Երբ այս գործառույթներին հետագա զանգեր կատարվեն, դրանք չեն հաշվարկվի, այլ արժեքները կկարդան համապատասխան դաշտերից:

Օգտագործելով այս մեխանիզմը, դուք կարող եք, օրինակ, ձերբազատվել հարցումների ռեկուրսիաներից (CTE): Մասնավորապես, հաշվի առեք խմբեր, որոնք ծառ են կազմում՝ օգտագործելով երեխա/ծնող հարաբերությունները (յուրաքանչյուր խումբ ունի իր ծնողի հղումը).

parent = DATA Group (Group);

Ֆունկցիոնալ տվյալների բազայում ռեկուրսիայի տրամաբանությունը կարող է սահմանվել հետևյալ կերպ.

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;

Քանի որ գործառույթի համար Ծնող է նշվում է ՆՅՈՒԹԱՑՎԱԾ, ապա դրա համար կստեղծվի երկու ստեղներով (խմբերով) աղյուսակ, որում դաշտը. Ծնող է ճիշտ կլինի միայն այն դեպքում, եթե առաջին բանալին երկրորդի երեխա է: Այս աղյուսակում գրառումների թիվը հավասար կլինի ծառի միջին խորության վրա բազմապատկած խմբերի թվին: Եթե ​​Ձեզ անհրաժեշտ է, օրինակ, հաշվել որոշակի խմբի հետնորդների թիվը, կարող եք օգտագործել այս ֆունկցիան.

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

SQL հարցումում CTE չի լինի: Փոխարենը կլինի պարզ GROUP BY:

Օգտագործելով այս մեխանիզմը, անհրաժեշտության դեպքում կարող եք նաև հեշտությամբ ապանորմալացնել տվյալների բազան.

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

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

Գործառույթ կանչելիս ամսաթիվ պատվերի տողի համար այն դաշտը, որի համար կա ինդեքս, կկարդացվի պատվերի տողերով աղյուսակից: Երբ պատվերի ամսաթիվը փոխվում է, համակարգն ինքնին ավտոմատ կերպով կվերահաշվարկի տողում չնորմալացված ամսաթիվը:

Առավելությունները

Ինչի՞ համար է այս ամբողջ մեխանիզմը։ Դասական DBMS-ներում, առանց հարցումների վերաշարադրման, ծրագրավորողը կամ DBA-ն կարող է միայն փոխել ինդեքսները, որոշել վիճակագրությունը և ասել հարցման պլանավորողին, թե ինչպես դրանք կատարել (իսկ HINT-ները հասանելի են միայն առևտրային DBMS-ներում): Որքան էլ նրանք փորձեն, նրանք չեն կարողանա լրացնել առաջին հարցումը հոդվածում O (բաժանմունքների թիվը) առանց հարցումները փոխելու կամ գործարկիչներ ավելացնելու: Առաջարկվող սխեմայում մշակման փուլում դուք պետք չէ մտածել տվյալների պահպանման կառուցվածքի և ագրեգացիաների մասին: Այս ամենը կարելի է հեշտությամբ փոխել թռիչքի ժամանակ, անմիջապես շահագործման մեջ:

Գործնականում դա այսպիսի տեսք ունի. Որոշ մարդիկ տրամաբանություն են զարգացնում ուղղակիորեն հիմնվելով առաջադրանքի վրա: Նրանք չեն հասկանում ալգորիթմները և դրանց բարդությունը, ոչ կատարման պլանները, ոչ միացման տեսակները, ոչ էլ որևէ այլ տեխնիկական բաղադրիչ: Այս մարդիկ ավելի շատ բիզնես վերլուծաբաններ են, քան մշակողներ: Այնուհետև այս ամենը անցնում է փորձարկման կամ շահագործման: Թույլ է տալիս գրանցել երկարատև հարցումները: Երբ հայտնաբերվում է երկար հարցում, այն ժամանակ այլ մարդիկ (ավելի տեխնիկական. հիմնականում DBA) որոշում են միացնել MATERIALIZED-ը որոշ միջանկյալ ֆունկցիայի վրա: Սա մի փոքր դանդաղեցնում է ձայնագրությունը (քանի որ դա պահանջում է գործարքի լրացուցիչ դաշտի թարմացում): Այնուամենայնիվ, ոչ միայն այս հարցումը զգալիորեն արագանում է, այլև բոլոր մյուսները, որոնք օգտագործում են այս գործառույթը: Միևնույն ժամանակ, որոշելը, թե որ գործառույթն է նյութականացվել, համեմատաբար պարզ է: Երկու հիմնական պարամետր՝ մուտքագրման հնարավոր արժեքների քանակը (սա թե քանի գրառում կլինի համապատասխան աղյուսակում), և որքան հաճախ է այն օգտագործվում այլ գործառույթներում:

Անալոգներ

Ժամանակակից առևտրային DBMS-ներն ունեն նմանատիպ մեխանիզմներ՝ ՆՅՈՒԹԱԿԱՆ ԴԻՏՈՒՄ FAST REFRESH-ով (Oracle) և INDEXED VIEW (Microsoft SQL Server): PostgreSQL-ում MATERIALIZED VIEW-ը չի կարող թարմացվել գործարքի մեջ, այլ միայն պահանջով (և նույնիսկ շատ խիստ սահմանափակումներով), ուստի մենք դա չենք համարում: Բայց նրանք ունեն մի քանի խնդիրներ, որոնք զգալիորեն սահմանափակում են դրանց օգտագործումը:

Նախ, դուք կարող եք միացնել նյութականացումը միայն այն դեպքում, եթե արդեն ստեղծել եք սովորական VIEW: Հակառակ դեպքում, դուք ստիպված կլինեք վերաշարադրել մնացած հարցումները՝ մուտք գործելու նորաստեղծ տեսք՝ այս նյութականացումն օգտագործելու համար: Կամ թողեք ամեն ինչ այնպես, ինչպես կա, բայց դա առնվազն անարդյունավետ կլինի, եթե կան որոշակի արդեն նախապես հաշվարկված տվյալներ, բայց շատ հարցումներ միշտ չէ, որ օգտագործում են դրանք, այլ վերահաշվարկում են դրանք։

Երկրորդ, նրանք ունեն հսկայական թվով սահմանափակումներ.

Oracle

5.3.8.4 Արագ թարմացման ընդհանուր սահմանափակումներ

Նյութականացված տեսակետի որոշիչ հարցումը սահմանափակվում է հետևյալ կերպ.

  • Նյութականացված տեսքը չպետք է պարունակի հղումներ չկրկնվող արտահայտությունների, ինչպիսիք են SYSDATE և ROWNUM.
  • Նյութականացված տեսակետը չպետք է պարունակի հղումներ RAW or LONG RAW տվյալների տեսակները.
  • Այն չի կարող պարունակել ա SELECT ցուցակի ենթահարկ.
  • Այն չի կարող պարունակել վերլուծական գործառույթներ (օրինակ. RANK) մեջ SELECT կետը:
  • Այն չի կարող հղում կատարել աղյուսակին, որի վրա ան XMLIndex ցուցանիշը սահմանվում է.
  • Այն չի կարող պարունակել ա MODEL կետը:
  • Այն չի կարող պարունակել ա HAVING կետ՝ ենթհարցմամբ։
  • Այն չի կարող պարունակել տեղադրված հարցումներ, որոնք ունեն ANY, ALLԿամ NOT EXISTS.
  • Այն չի կարող պարունակել ա [START WITH …] CONNECT BY կետը:
  • Այն չի կարող պարունակել մի քանի մանրամասն աղյուսակներ տարբեր կայքերում:
  • ON COMMIT նյութականացված դիտումները չեն կարող ունենալ հեռավոր մանրամասների աղյուսակներ:
  • Ներդրված նյութականացված դիտումները պետք է ունենան միացում կամ ագրեգատ:
  • Նյութականացված միացվող տեսակետները և նյութականացված համախառն տեսակետները ա GROUP BY կետը չի կարող ընտրել ինդեքսով կազմակերպված աղյուսակից:

5.3.8.5 Արագ թարմացման սահմանափակումներ նյութականացված դիտումների վրա միայն միացումներով

Նյութականացված դիտումների համար հարցումների սահմանումը միայն միացումներով և առանց ագրեգատների ունի արագ թարմացման հետևյալ սահմանափակումները.

  • Բոլոր սահմանափակումները «Արագ թարմացման ընդհանուր սահմանափակումներ»:
  • Նրանք չեն կարող ունենալ GROUP BY կետերը կամ ագրեգատները:
  • Բոլոր աղյուսակների շարքերը FROM ցանկը պետք է հայտնվի SELECT հարցման ցուցակը.
  • Նյութականացված դիտումների մատյանները պետք է գոյություն ունենան տողերով բոլոր հիմնական աղյուսակների համար FROM հարցման ցուցակը.
  • Դուք չեք կարող ստեղծել արագ թարմացվող նյութականացված տեսք բազմաթիվ աղյուսակներից պարզ միացումներով, որոնք ներառում են օբյեկտի տիպի սյունակում: SELECT հայտարարության մեջ:

Բացի այդ, ձեր ընտրած թարմացման մեթոդը օպտիմալ արդյունավետ չի լինի, եթե.

  • Որոշիչ հարցումն օգտագործում է արտաքին միացում, որն իրեն պահում է ներքին միացման նման: Եթե ​​որոշիչ հարցումը պարունակում է նման միացում, մտածեք վերագրել որոշիչ հարցումը՝ ներքին միացում պարունակելու համար:
  • The SELECT նյութականացված տեսքի ցանկը պարունակում է արտահայտություններ բազմաթիվ աղյուսակների սյունակների վրա:

5.3.8.6 ագրեգատներով նյութականացված դիտումների արագ թարմացման սահմանափակումներ

Նյութականացված դիտումների հարցումների սահմանումը ագրեգատներով կամ միացումներով ունի արագ թարմացման հետևյալ սահմանափակումները.

Արագ թարմացումը աջակցվում է երկուսի համար էլ ON COMMIT և ON DEMAND նյութականացված տեսակետներ, սակայն կիրառվում են հետևյալ սահմանափակումները.

  • Նյութականացված տեսքի բոլոր աղյուսակները պետք է ունենան նյութականացված տեսքի մատյաններ, իսկ նյութականացված տեսքի մատյանները պետք է.
    • Պարունակեք բոլոր սյունակները աղյուսակից, որը նշված է նյութականացված տեսքում:
    • Նշեք հետ ROWID և INCLUDING NEW VALUES.
    • նշեք SEQUENCE դրույթ, եթե ակնկալվում է, որ աղյուսակը կունենա ներդիրների/ուղղակի բեռնումների, ջնջումների և թարմացումների խառնուրդ:

  • Միայն SUM, COUNT, AVG, STDDEV, VARIANCE, MIN և MAX աջակցվում են արագ թարմացման համար:
  • COUNT(*) պետք է հստակեցվի.
  • Ագրեգատային ֆունկցիաները պետք է լինեն միայն որպես արտահայտության ամենահեռավոր մաս: Այսինքն, ագրեգատներ, ինչպիսիք են AVG(AVG(x)) or AVG(x)+ AVG(x) չեն թույլատրվում:
  • Յուրաքանչյուր ագրեգատի համար, ինչպիսին է AVG(expr), համապատասխան COUNT(expr) պետք է ներկա լինի. Oracle-ը դա խորհուրդ է տալիս SUM(expr) հստակեցվի.
  • If VARIANCE(expr) or STDDEV(expr) նշված է, COUNT(expr) և SUM(expr) պետք է հստակեցվի. Oracle-ը դա խորհուրդ է տալիս SUM(expr *expr) հստակեցվի.
  • The SELECT Սահմանող հարցման սյունակը չի կարող լինել մի քանի հիմնական աղյուսակների սյունակներով բարդ արտահայտություն: Դրա հնարավոր լուծումը ներկառուցված նյութական տեսքի օգտագործումն է:
  • The SELECT ցանկը պետք է պարունակի բոլորը GROUP BY սյուներ:
  • Նյութականացված տեսակետը հիմնված չէ մեկ կամ մի քանի հեռավոր աղյուսակների վրա:
  • Եթե ​​օգտագործում եք a CHAR Նյութականացված դիտումների մատյանի ֆիլտրի սյունակներում տվյալների տեսակը, հիմնական կայքի նիշերի հավաքածուները և նյութականացված տեսքը պետք է լինեն նույնը:
  • Եթե ​​նյութականացված տեսքն ունի հետևյալներից մեկը, ապա արագ թարմացումը աջակցվում է միայն սովորական DML ներդիրների և ուղղակի բեռների վրա:
    • Նյութականացված տեսակետների հետ MIN or MAX ագրեգատներ
    • Նյութականացված տեսակետներ, որոնք ունեն SUM(expr) բայց ոչ COUNT(expr)
    • Նյութականացված տեսակետներ առանց COUNT(*)

    Նման նյութականացված տեսակետը կոչվում է միայն ներդիրով նյութականացված տեսակետ:

  • Նյութականացված տեսակետ հետ MAX or MIN արագ թարմացվում է ջնջված կամ խառնված DML հայտարարություններից հետո, եթե այն չունի a WHERE կետը:
    Առավելագույն/րոպե արագ թարմացումը ջնջելուց կամ խառնված DML-ից հետո նույն վարքագիծը չունի, ինչ միայն ներդիրի դեպքում: Այն ջնջում և վերահաշվարկում է առավելագույն/րոպե արժեքները տուժած խմբերի համար: Դուք պետք է տեղյակ լինեք դրա կատարողականի ազդեցության մասին:
  • Նյութականացված տեսակետներ՝ անվանված դիտումներով կամ ենթհարցումներով FROM կետը կարող է արագ թարմացվել, պայմանով, որ դիտումները կարող են ամբողջությամբ միաձուլվել: Տեղեկությունների համար, թե որ դիտումները կմիավորվեն, տե՛ս Oracle Database SQL լեզվի տեղեկանք.
  • Եթե ​​չկան արտաքին միացումներ, դուք կարող եք ունենալ կամայական ընտրություն և միանալ դրան WHERE կետը:
  • Արտաքին միացումներով նյութականացված ագրեգատային տեսքերը արագ թարմացվում են սովորական DML-ից և ուղղակի բեռներից հետո, պայմանով, որ միայն արտաքին աղյուսակը փոփոխված է: Բացի այդ, եզակի սահմանափակումներ պետք է լինեն ներքին միացման աղյուսակի միացման սյունակների վրա: Եթե ​​կան արտաքին միացումներ, ապա բոլոր միացումները պետք է միացված լինեն ANDs և պետք է օգտագործի հավասարությունը (=) օպերատոր:
  • հետ նյութականացված տեսակետների համար CUBE, ROLLUP, խմբերի խմբավորում կամ դրանց միացում, կիրառվում են հետևյալ սահմանափակումները.
    • The SELECT ցանկը պետք է պարունակի խմբավորման տարբերակիչ, որը կարող է լինել կամ a GROUPING_ID գործառույթ բոլորի վրա GROUP BY արտահայտություններ կամ GROUPING գործառույթներ յուրաքանչյուրի համար մեկ GROUP BY արտահայտություն. Օրինակ, եթե GROUP BY նյութականացված տեսակետի կետն է.GROUP BY CUBE(a, b)», ապա SELECT ցանկը պետք է պարունակի կամ «GROUPING_ID(a, b)" կամ "GROUPING(a) AND GROUPING(b)» որպեսզի նյութականացված տեսքը արագ թարմացվի:
    • GROUP BY չպետք է հանգեցնի որևէ կրկնակի խմբավորման: Օրինակ, "GROUP BY a, ROLLUP(a, b)«Արագ թարմացվող չէ, քանի որ դա հանգեցնում է կրկնակի խմբավորումների»:(a), (a, b), AND (a)»:

5.3.8.7 UNION ALL-ի հետ նյութականացված տեսակետների արագ թարմացման սահմանափակումներ

Նյութականացված տեսակետներ հետ UNION ALL սահմանել օպերատորի աջակցությունը REFRESH FAST տարբերակ, եթե բավարարված են հետևյալ պայմանները.

  • Սահմանող հարցումը պետք է ունենա UNION ALL օպերատոր բարձր մակարդակի վրա:

    The UNION ALL օպերատորը չի կարող ներկառուցվել ենթհարցման մեջ, մեկ բացառությամբ՝ The UNION ALL կարող է լինել ենթհարցման մեջ FROM դրույթ, պայմանով, որ որոշիչ հարցումը ձևի է SELECT * FROM (դիտել կամ ենթահղում հետ UNION ALL) ինչպես հետևյալ օրինակում.

    ՍՏԵՂԾԵԼ VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM հաճախորդներից c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM հաճախորդներից c WHERE cWHERE c. «Ջոնս»); ՍՏԵՂԾԵԼ ՆՅՈՒԹԱԿԱՆ ԴԻՏՔ unionall_inside_view_mv ԹԱՐՄԱՑՆԵԼ ԱՐԱԳ ՊԱՀԱՆՋՈՎ ՈՐՊԵՍ Ընտրված * View_with_unionall-ից;
    

    Նշենք, որ տեսակետը view_with_unionall բավարարում է արագ թարմացման պահանջները:

  • Յուրաքանչյուր հարցման բլոկ մեջ UNION ALL հարցումը պետք է բավարարի ագրեգատներով արագ թարմացվող նյութականացված տեսքի կամ միացումներով արագ թարմացվող նյութականացված տեսքի պահանջներին:

    Համապատասխան նյութականացված տեսքի մատյանները պետք է ստեղծվեն աղյուսակների վրա, ինչպես պահանջվում է արագ թարմացվող նյութականացված տեսքի համապատասխան տեսակի համար:
    Նկատի ունեցեք, որ Oracle Database-ը նաև թույլ է տալիս մեկ աղյուսակի նյութականացված տեսքի հատուկ դեպք՝ միայն տրամադրված միացումներով ROWID սյունակը ներառվել է SELECT ցանկը և նյութականացված դիտման մատյանում: Սա ցուցադրվում է դիտման որոշիչ հարցումում view_with_unionall.

  • The SELECT յուրաքանչյուր հարցման ցանկը պետք է ներառի ա UNION ALL մարկեր, և UNION ALL սյունակը յուրաքանչյուրում պետք է ունենա հստակ հաստատուն թվային կամ լարային արժեք UNION ALL մասնաճյուղ. Ավելին, նշիչի սյունակը պետք է հայտնվի նույն հերթական դիրքում SELECT յուրաքանչյուր հարցման բլոկի ցուցակ: Տեսնել "UNION ALL Marker և Query Rewrite» վերաբերյալ լրացուցիչ տեղեկությունների համար UNION ALL մարկերներ
  • Որոշ առանձնահատկություններ, ինչպիսիք են արտաքին միացումները, միայն ներդիրով նյութականացված դիտումների հարցումները և հեռավոր աղյուսակները, չեն աջակցվում նյութականացված դիտումների համար UNION ALL. Այնուամենայնիվ, նշեք, որ կրկնօրինակման մեջ օգտագործվող նյութականացված դիտումները, որոնք չեն պարունակում միացումներ կամ ագրեգատներ, կարող են արագ թարմացվել, երբ UNION ALL կամ օգտագործվում են հեռավոր սեղաններ:
  • Համատեղելիության սկզբնավորման պարամետրը պետք է սահմանվի 9.2.0 կամ ավելի բարձր՝ արագ թարմացվող նյութականացված տեսք ստեղծելու համար։ UNION ALL.

Չեմ ուզում վիրավորել Oracle-ի երկրպագուներին, բայց դատելով նրանց սահմանափակումների ցանկից՝ թվում է, որ այս մեխանիզմը գրվել է ոչ թե ընդհանուր դեպքում՝ օգտագործելով ինչ-որ մոդել, այլ հազարավոր հնդկացիներ, որտեղ բոլորին հնարավորություն է տրվել. գրեն իրենց սեփական ճյուղը, և նրանցից յուրաքանչյուրն արեց այն, ինչ կարող էր և արեց: Այս մեխանիզմն իրական տրամաբանության համար օգտագործելը նման է ականապատ դաշտով քայլելուն: Դուք կարող եք ցանկացած պահի ական ստանալ՝ սեղմելով ոչ ակնհայտ սահմանափակումներից մեկը: Թե ինչպես է այն աշխատում, նույնպես առանձին հարց է, բայց դա դուրս է այս հոդվածի շրջանակներից:

Microsoft SQL Server

Լրացուցիչ պահանջներ

Ի լրումն SET տարբերակների և դետերմինիստական ​​ֆունկցիայի պահանջների, պետք է բավարարվեն հետևյալ պահանջները.

  • Օգտագործողը, որը կատարում է CREATE INDEX պետք է լինի տեսարանի տերը:
  • Երբ դուք ստեղծում եք ինդեքսը, IGNORE_DUP_KEY տարբերակը պետք է սահմանվի OFF (կանխադրված պարամետր):
  • Աղյուսակները պետք է հիշատակվեն երկու մասից բաղկացած անուններով, սխեմա.սեղանի անվանումը դիտման սահմանման մեջ:
  • Օգտատիրոջ կողմից սահմանված գործառույթները, որոնք վկայակոչվում են դիտման մեջ, պետք է ստեղծվեն՝ օգտագործելով WITH SCHEMABINDING տարբերակ.
  • Օգտատիրոջ կողմից սահմանված ցանկացած գործառույթ, որը հղում է արվում դիտման մեջ, պետք է հիշատակվի երկու մասից բաղկացած անուններով, ..
  • Օգտատիրոջ կողմից սահմանված գործառույթի տվյալների հասանելիության հատկությունը պետք է լինի NO SQL, և արտաքին մուտքի հատկությունը պետք է լինի NO.
  • Ընդհանուր լեզվի գործարկման ժամանակի (CLR) գործառույթները կարող են հայտնվել դիտման ընտրված ցանկում, բայց չեն կարող լինել կլաստերացված ինդեքսային բանալի սահմանման մաս: CLR գործառույթները չեն կարող հայտնվել դիտման WHERE կետում կամ դիտման մեջ JOIN գործողության ON կետում:
  • CLR գործառույթները և CLR-ի օգտագործողի կողմից սահմանված տեսակների մեթոդները, որոնք օգտագործվում են դիտման սահմանման մեջ, պետք է ունենան այն հատկությունները, որոնք սահմանված են հետևյալ աղյուսակում:

    Սեփականություն
    Նշում

    ԴԵՏԵՐՄԻՆԻՍՏԱԿԱՆ = ՃԻՇՏ
    Պետք է հստակորեն հայտարարված լինի որպես Microsoft .NET Framework մեթոդի հատկանիշ:

    Ճշգրիտ = ՃՇՄԱՐՏ
    Պետք է հստակորեն հայտարարվի որպես .NET Framework մեթոդի հատկանիշ:

    ՏՎՅԱԼՆԵՐԻ ՄՈՒՏՔ = SQL ՉԿԱ
    Որոշվում է՝ «DataAccess» հատկանիշը դնելով «DataAccessKind.None» և «SystemDataAccess» հատկանիշը՝ «SystemDataAccessKind.None»:

    ԱՐՏԱՔԻՆ ՄՈՒՏՔ = NO
    Այս հատկությունը կանխադրված է NO-ի CLR ռեժիմների համար:

  • Տեսարանը պետք է ստեղծվի՝ օգտագործելով WITH SCHEMABINDING տարբերակ.
  • Դիտումը պետք է հղում կատարի միայն բազային աղյուսակներին, որոնք գտնվում են նույն տվյալների բազայում, ինչ դիտումը: Տեսակետը չի կարող հղում կատարել այլ տեսակետների:
  • View-ի սահմանման SELECT դրույթը չպետք է պարունակի հետևյալ Transact-SQL տարրերը.

    COUNT
    ROWSET ֆունկցիաներ (OPENDATASOURCE, OPENQUERY, OPENROWSETԵՎ OPENXML)
    OUTER միանում է (LEFT, RIGHTԿամ FULL)

    Ստացված աղյուսակը (սահմանվում է՝ նշելով a SELECT հայտարարությունը FROM կետ)
    Ինքնակցում
    Նշելով սյունակները՝ օգտագործելով SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARPԿամ AVG
    Սեղանի ընդհանուր արտահայտություն (CTE)

    բոց1, տեքստ, ntext, պատկեր, XMLԿամ ֆայլի հոսք սյունակ
    Ենթահարկ
    OVER կետ, որը ներառում է դասակարգման կամ համախառն պատուհանի գործառույթները

    Ամբողջական տեքստի նախադեպեր (CONTAINS, FREETEXT)
    SUM ֆունկցիա, որը հղում է անում զրոյական արտահայտությանը
    ORDER BY

    CLR օգտագործողի կողմից սահմանված ագրեգատ գործառույթ
    TOP
    CUBE, ROLLUPԿամ GROUPING SETS օպերատորներ

    MIN, MAX
    UNION, EXCEPTԿամ INTERSECT օպերատորներ
    TABLESAMPLE

    Աղյուսակի փոփոխականներ
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Սյունակների նոսր հավաքածուներ
    Ներկառուցված (TVF) կամ բազմակողմանի աղյուսակի արժեքավոր գործառույթներ (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Ինդեքսավորված տեսքը կարող է պարունակել բոց սյունակներ; սակայն, նման սյունակները չեն կարող ներառվել կլաստերային ինդեքսային բանալիում:

  • If GROUP BY առկա է, VIEW սահմանումը պետք է պարունակի COUNT_BIG(*) և չպետք է պարունակի HAVING, Սրանք GROUP BY սահմանափակումները կիրառելի են միայն ինդեքսավորված տեսքի սահմանման համար: Հարցումը կարող է օգտագործել ինդեքսավորված տեսք իր կատարման պլանում, նույնիսկ եթե այն չի բավարարում դրանց GROUP BY սահմանափակումներ:
  • Եթե ​​դիտման սահմանումը պարունակում է ա GROUP BY կետում, եզակի կլաստերային ինդեքսի բանալին կարող է հղում կատարել միայն սյունակում նշված սյունակներին GROUP BY կետը:

Այստեղ պարզ է, որ հնդիկները ներգրավված չեն եղել, քանի որ նրանք որոշել են դա անել «քիչ, բայց լավ կանենք» սխեմայի համաձայն: Այսինքն՝ դաշտում ավելի շատ ականներ ունեն, բայց նրանց գտնվելու վայրը ավելի թափանցիկ է։ Ամենահիասթափեցնողն այս սահմանափակումն է.

Դիտումը պետք է հղում կատարի միայն բազային աղյուսակներին, որոնք գտնվում են նույն տվյալների բազայում, ինչ դիտումը: Տեսակետը չի կարող հղում կատարել այլ տեսակետների:

Մեր տերմինաբանության մեջ սա նշանակում է, որ ֆունկցիան չի կարող մուտք գործել մեկ այլ նյութականացված ֆունկցիա: Սա կտրում է բոլոր գաղափարախոսությունները սկզբում:
Նաև այս սահմանափակումը (և հետագայում տեքստում) մեծապես նվազեցնում է օգտագործման դեպքերը.

View-ի սահմանման SELECT դրույթը չպետք է պարունակի հետևյալ Transact-SQL տարրերը.

COUNT
ROWSET ֆունկցիաներ (OPENDATASOURCE, OPENQUERY, OPENROWSETԵՎ OPENXML)
OUTER միանում է (LEFT, RIGHTԿամ FULL)

Ստացված աղյուսակը (սահմանվում է՝ նշելով a SELECT հայտարարությունը FROM կետ)
Ինքնակցում
Նշելով սյունակները՝ օգտագործելով SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARPԿամ AVG
Սեղանի ընդհանուր արտահայտություն (CTE)

բոց1, տեքստ, ntext, պատկեր, XMLԿամ ֆայլի հոսք սյունակ
Ենթահարկ
OVER կետ, որը ներառում է դասակարգման կամ համախառն պատուհանի գործառույթները

Ամբողջական տեքստի նախադեպեր (CONTAINS, FREETEXT)
SUM ֆունկցիա, որը հղում է անում զրոյական արտահայտությանը
ORDER BY

CLR օգտագործողի կողմից սահմանված ագրեգատ գործառույթ
TOP
CUBE, ROLLUPԿամ GROUPING SETS օպերատորներ

MIN, MAX
UNION, EXCEPTԿամ INTERSECT օպերատորներ
TABLESAMPLE

Աղյուսակի փոփոխականներ
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Սյունակների նոսր հավաքածուներ
Ներկառուցված (TVF) կամ բազմակողմանի աղյուսակի արժեքավոր գործառույթներ (MSTVF)
OFFSET

CHECKSUM_AGG

ԱՐԳԵԼՎՈՒՄ ԵՆ ԱՐՏԱՔԻՆ ՄԻԱՑՈՒՄՆԵՐԸ, ՄԻՈՒԹՅՈՒՆԸ, ՊԱՏՎԻՐՈՒՄԸ և այլն: Գուցե ավելի հեշտ կլիներ նշել, թե ինչ կարող է օգտագործվել, քան թե ինչը չի կարող օգտագործվել: Ցուցակը հավանաբար շատ ավելի փոքր կլիներ։

Ամփոփելու համար. LGPL տեխնոլոգիայի յուրաքանչյուր (եկեք նշենք կոմերցիոն) DBMS-ում ընդդեմ որևէ (բացառությամբ մեկ տրամաբանական, ոչ տեխնիկական) սահմանափակումների մի հսկայական շարք: Այնուամենայնիվ, հարկ է նշել, որ հարաբերական տրամաբանության մեջ այս մեխանիզմի ներդրումը որոշ չափով ավելի դժվար է, քան նկարագրված ֆունկցիոնալ տրամաբանության մեջ:

Իրականացման

Ինչպես է դա աշխատում? PostgreSQL-ն օգտագործվում է որպես «վիրտուալ մեքենա»: Ներսում կա բարդ ալգորիթմ, որը ստեղծում է հարցումներ: Այստեղ աղբյուրը. Եվ կա ոչ միայն էվրիստիկայի մի մեծ շարք՝ եթե-ների փունջով: Այսպիսով, եթե դուք ունեք մի երկու ամիս սովորելու համար, կարող եք փորձել հասկանալ ճարտարապետությունը:

Արդյո՞ք այն արդյունավետ է աշխատում: Բավական արդյունավետ։ Ցավոք սրտի, դա դժվար է ապացուցել։ Կարող եմ միայն ասել, որ եթե հաշվի առնեք հազարավոր հարցումները, որոնք առկա են մեծ հավելվածներում, ապա միջինում դրանք ավելի արդյունավետ են, քան լավ մշակողների հարցերը: Գերազանց SQL ծրագրավորողը կարող է ցանկացած հարցում գրել ավելի արդյունավետ, բայց հազար հարցումներով նա պարզապես մոտիվացիա կամ ժամանակ չի ունենա դա անելու: Միակ բանը, որ այժմ կարող եմ որպես արդյունավետության ապացույց նշել, այն է, որ մի քանի նախագծեր աշխատում են այս DBMS-ի վրա կառուցված հարթակի վրա։ ERP համակարգեր, որոնք ունեն հազարավոր տարբեր ՆՅՈՒԹԱԿԱՆ գործառույթներ, հազարավոր օգտատերերով և տերաբայթ տվյալների բազաներով հարյուր միլիոնավոր գրառումներով, որոնք աշխատում են սովորական երկու պրոցեսորային սերվերի վրա: Այնուամենայնիվ, ցանկացած մարդ կարող է ստուգել/հերքել արդյունավետությունը՝ ներբեռնելով մի հարթակ և PostgreSQL, միացված գրանցել SQL հարցումները և փորձել փոխել այնտեղի տրամաբանությունն ու տվյալները:

Հետևյալ հոդվածներում ես կխոսեմ նաև այն մասին, թե ինչպես կարող եք սահմանափակումներ սահմանել գործառույթների վրա, աշխատել փոփոխության նիստերի հետ և շատ ավելին:

Source: www.habr.com

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