Ekvilibro skribas kaj legas en la datumbazo

Ekvilibro skribas kaj legas en la datumbazo
En la antaŭa artikolo Mi priskribis la koncepton kaj efektivigon de datumbazo konstruita surbaze de funkcioj, prefere ol tabeloj kaj kampoj kiel en interrilataj datumbazoj. Ĝi disponigis multajn ekzemplojn montrantajn la avantaĝojn de tiu aliro super la klasika. Multaj trovis ilin ne sufiĉe konvinkaj.

En ĉi tiu artikolo, mi montros kiel ĉi tiu koncepto permesas vin rapide kaj oportune ekvilibrigi skribadon kaj legadon al la datumbazo sen ajna ŝanĝo en la operacia logiko. Simila funkcieco estis provita esti efektivigita en modernaj komercaj DBMSoj (aparte, Oracle kaj Microsoft SQL Server). Fine de la artikolo mi montros, ke tio, kion ili faris, milde, ne tre bone funkciis.

Priskribo

Kiel antaŭe, por pli bona kompreno mi komencos la priskribon per ekzemploj. Ni diru, ke ni devas efektivigi logikon, kiu redonos liston de fakoj kun la nombro da dungitoj en ili kaj ilia totala salajro.

En funkcia datumbazo ĝi aspektus jene:

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

La komplekseco de ekzekuto de ĉi tiu demando en iu ajn DBMS ekvivalentos al O (nombro da dungitoj)ĉar ĉi tiu kalkulo postulas skanadon de la tuta tabelo de dungitoj kaj poste grupigi ilin laŭ fako. Ankaŭ estos iom da eta (ni kredas ke estas multe pli da dungitoj ol fakoj) suplemento depende de la elektita plano. O (registra nombro da dungitoj)O (nombro da fakoj) por grupigo ktp.

Estas klare, ke la ekzekuta superkosto povas esti malsama en malsamaj DBMSoj, sed la komplekseco neniel ŝanĝiĝos.

En la proponita efektivigo, la funkcia DBMS generos unu subdemandon, kiu kalkulos la postulatajn valorojn por la fako, kaj poste faros JOIN kun la faka tablo por akiri la nomon. Tamen, por ĉiu funkcio, kiam oni deklaras, eblas agordi specialan MATERIALIZITA markilo. La sistemo aŭtomate kreos respondan kampon por ĉiu tia funkcio. Ŝanĝante la valoron de funkcio, la valoro de la kampo ankaŭ ŝanĝiĝos en la sama transakcio. Alirante ĉi tiun funkcion, la antaŭkalkulita kampo estos alirita.

Precipe, se vi agordas MATERIALIZED por funkcioj kalkuliDungitojn и salajroSum, tiam du kampoj estos aldonitaj al la tabelo kun la listo de fakoj, kiu stokos la nombron da dungitoj kaj ilian totalan salajron. Kiam ajn estas ŝanĝo en dungitoj, iliaj salajroj aŭ fakaj aliĝoj, la sistemo aŭtomate ŝanĝos la valorojn de ĉi tiuj kampoj. La supra demando aliros ĉi tiujn kampojn rekte kaj estos efektivigita en O (nombro da fakoj).

Kio estas la limigoj? Nur unu afero: tia funkcio devas havi finian nombron da enigvaloroj por kiuj ĝia valoro estas difinita. Alie, estos neeble konstrui tabelon, kiu stokas ĉiujn ĝiajn valorojn, ĉar ne povas ekzisti tabelo kun senfina nombro da vicoj.

Ekzemplo:

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

Ĉi tiu funkcio estas difinita por senfina nombro da valoroj de N (ekzemple, ajna negativa valoro taŭgas). Tial, vi ne povas meti MATERIALIZED sur ĝin. Do ĉi tio estas logika limigo, ne teknika (tio estas, ne ĉar ni ne povis efektivigi ĝin). Alie, ne estas limigoj. Vi povas uzi grupiĝojn, ordigon, KAJ kaj AŬ, PARTITION, rikurson ktp.

Ekzemple, en problemo 2.2 de la antaŭa artikolo, vi povas meti MATERIALIZED sur ambaŭ funkciojn:

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;

La sistemo mem kreos unu tabelon kun tipklavoj kliento, Produkto и ENTJERO, aldonos du kampojn al ĝi kaj ĝisdatigos la kampovalorojn en ili kun ajnaj ŝanĝoj. Kiam pliaj alvokoj al ĉi tiuj funkcioj estas faritaj, ili ne estos kalkulitaj, sed prefere la valoroj estos legitaj el la respondaj kampoj.

Uzante ĉi tiun mekanismon, vi povas, ekzemple, forigi rekursiojn (CTE) en demandoj. Aparte, konsideru grupojn kiuj formas arbon uzante la infanon/gepatron rilaton (ĉiu grupo havas ligon al sia gepatro):

parent = DATA Group (Group);

En funkcia datumbazo, rekursia logiko povas esti precizigita jene:

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;

Ekde por la funkcio estas Gepatro estas markita MATERIALIZITA, tiam tabelo kun du ŝlosiloj (grupoj) estos kreita por ĝi, en kiu la kampo estas Gepatro estos vera nur se la unua ŝlosilo estas filo de la dua. La nombro da enskriboj en ĉi tiu tabelo estos egala al la nombro da grupoj multiplikita per la averaĝa profundo de la arbo. Se vi bezonas, ekzemple, kalkuli la nombron da posteuloj de certa grupo, vi povas uzi ĉi tiun funkcion:

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

Ne estos CTE en la SQL-demando. Anstataŭe estos simpla GROUP BY.

Uzante ĉi tiun mekanismon, vi ankaŭ povas facile malnormaligi la datumbazon se necese:

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

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

Kiam oni vokas funkcion dato por la ordlinio, la kampo por kiu estas indekso estos legata de la tabelo kun ordlinioj. Kiam la mendodato ŝanĝiĝas, la sistemo mem aŭtomate rekalkulos la malnormaligitan daton en la linio.

Profitoj

Por kio estas ĉi tiu tuta mekanismo? En klasikaj DBMSoj, sen reverkado de demandoj, programisto aŭ DBA povas nur ŝanĝi indeksojn, determini statistikojn kaj diri al la demandplanisto kiel ekzekuti ilin (kaj HINToj estas nur haveblaj en komercaj DBMSoj). Kiom ajn ili klopodos, ili ne povos plenumi la unuan demandon en la artikolo en O (nombro da fakoj) sen ŝanĝi demandojn aŭ aldoni ellasilon. En la proponita skemo, en la disvolva etapo vi ne devas pensi pri la datuma stokado strukturo kaj kiujn agregaĵoj uzi. Ĉio ĉi povas esti facile ŝanĝita sur la flugo, rekte en funkciado.

Praktike ĝi aspektas tiel. Iuj homoj disvolvas logikon rekte surbaze de la tasko. Ili ne komprenas algoritmojn kaj ilian kompleksecon, nek ekzekutplanojn, nek specojn de kuniĝoj, nek ajnan alian teknikan komponanton. Ĉi tiuj homoj estas pli komercaj analizistoj ol programistoj. Tiam ĉio ĉi eniras testadon aŭ funkciadon. Ebligas ensalutu de longdaŭraj demandoj. Kiam longa demando estas detektita, tiam aliaj homoj (pli teknikaj - esence DBA) decidas ebligi MATERIALIZED sur iu meza funkcio. Ĉi tio iom malrapidigas la registradon (ĉar ĝi postulas ĝisdatigon de plia kampo en la transakcio). Tamen, ne nur ĉi tiu demando estas signife plirapidigita, sed ankaŭ ĉiuj aliaj, kiuj uzas ĉi tiun funkcion. Samtempe, decidi kiun funkcion materiigi estas relative facila. Du ĉefaj parametroj: la nombro da eblaj enigvaloroj (jen kiom da registroj estos en la responda tabelo), kaj kiom ofte ĝi estas uzata en aliaj funkcioj.

Analogoj

Modernaj komercaj DBMS-oj havas similajn mekanismojn: MATERIALIZITA VIDON kun RAPIDA REFRESH (Orakolo) kaj INDEXED VIEW (Microsoft SQL Server). En PostgreSQL, MATERIALIZED VIEW ne povas esti ĝisdatigita en transakcio, sed nur laŭpeto (kaj eĉ kun tre striktaj limigoj), do ni ne konsideras ĝin. Sed ili havas plurajn problemojn, kiuj signife limigas ilian uzon.

Unue, vi povas nur ebligi materiigon se vi jam kreis regulan VIDON. Alie, vi devos reverki la ceterajn petojn por aliri la nove kreitan vidon por uzi ĉi tiun materialigon. Aŭ lasu ĉion kiel ĝi estas, sed ĝi estos almenaŭ senefika, se ekzistas certaj jam antaŭkalkulitaj datumoj, sed multaj konsultoj ne ĉiam uzas ĝin, sed rekalkulas ĝin.

Due, ili havas grandan nombron da limigoj:

plejsanktejo

5.3.8.4 Ĝeneralaj Limigoj pri Rapida Refreŝiĝo

La difina demando de la materiigita vido estas limigita jene:

  • La materiigita vido ne devas enhavi referencojn al ne-ripetantaj esprimoj kiel SYSDATE kaj ROWNUM.
  • La realigita vido ne devas enhavi referencojn al RAW or LONG RAW datumtipoj.
  • Ĝi ne povas enhavi a SELECT listsubdemando.
  • Ĝi ne povas enhavi analizajn funkciojn (ekzemple, RANK) en la SELECT klaŭzo.
  • Ĝi ne povas referenci tabelon sur kiu an XMLIndex indekso estas difinita.
  • Ĝi ne povas enhavi a MODEL klaŭzo.
  • Ĝi ne povas enhavi a HAVING subfrazo kun subdemando.
  • Ĝi ne povas enhavi nestitajn demandojn kiuj havas ANY, ALLNOT EXISTS.
  • Ĝi ne povas enhavi a [START WITH …] CONNECT BY klaŭzo.
  • Ĝi ne povas enhavi plurajn detaltablojn ĉe malsamaj retejoj.
  • ON COMMIT materiigitaj vidoj ne povas havi forajn detaltablojn.
  • Nestitaj materiigitaj vidoj devas havi kunigon aŭ agregaĵon.
  • Materiigitaj kunigitaj vidoj kaj materiigitaj entutaj vidoj kun a GROUP BY subfrazo ne povas elekti el indeks-organizita tabelo.

5.3.8.5 Limigoj pri Rapida Refreŝiĝo ĉe Materiigitaj Vidoj kun Nur Kuniĝoj

Difini demandojn por realigitaj vidoj kun kuniĝoj nur kaj neniuj agregaĵoj havas la jenajn limigojn pri rapida refreŝiĝo:

  • Ĉiuj limigoj de «Ĝeneralaj Limigoj pri Rapida Refreŝiĝo".
  • Ili ne povas havi GROUP BY subfrazoj aŭ agregaĵoj.
  • Vicoj de ĉiuj tabloj en la FROM listo devas aperi en la SELECT listo de la demando.
  • Materiigitaj vidaj protokoloj devas ekzisti kun rowids por ĉiuj bazaj tabeloj en la FROM listo de la demando.
  • Vi ne povas krei rapidan refreŝigeblan materiigitan vidon el pluraj tabeloj kun simplaj kuniĝoj, kiuj inkluzivas objekto-tipan kolumnon en la SELECT deklaro.

Ankaŭ, la refreŝiga metodo, kiun vi elektas, ne estos optimume efika se:

  • La difina demando uzas eksteran kunigon kiu kondutas kiel interna kunigo. Se la difina demando enhavas tian kunigon, konsideru reverki la difinan demandon por enhavi internan kunigon.
  • la SELECT listo de la materiigita vido enhavas esprimojn sur kolumnoj de pluraj tabeloj.

5.3.8.6 Limigoj pri Rapida Refreŝiĝo sur Materiigitaj Vidoj kun Agregaĵoj

Difini demandojn por realigitaj vidoj kun agregaĵoj aŭ kuniĝoj havas la jenajn limigojn pri rapida refreŝiĝo:

Rapida refreŝiĝo estas subtenata por ambaŭ ON COMMIT kaj ON DEMAND realigitaj vidoj, tamen validas la sekvaj limigoj:

  • Ĉiuj tabeloj en la materiigita vido devas havi materiigitajn vidajn protokolojn, kaj la materiigitajn vidprotokolojn devas:
    • Enhavu ĉiujn kolumnojn de la tabelo referencita en la materiigita vido.
    • Indiku kun ROWID kaj INCLUDING NEW VALUES.
    • Specifi la SEQUENCE klaŭzo se la tabelo estas atendita havi miksaĵon de enigaĵoj/rektaj ŝarĝoj, forigoj kaj ĝisdatigoj.

  • nur SUM, COUNT, AVG, STDDEV, VARIANCE, MIN kaj MAX estas subtenataj por rapida refreŝiĝo.
  • COUNT(*) devas esti specifita.
  • Agregaj funkcioj devas okazi nur kiel la plej ekstera parto de la esprimo. Tio estas, agregaĵoj kiel ekz AVG(AVG(x)) or AVG(x)+ AVG(x) ne rajtas.
  • Por ĉiu agregaĵo kiel ekzemple AVG(expr), la responda COUNT(expr) devas ĉeesti. Oracle rekomendas tion SUM(expr) estu specifita.
  • If VARIANCE(expr) or STDDEV(expr) estas specifita, COUNT(expr) kaj SUM(expr) devas esti specifita. Oracle rekomendas tion SUM(expr *expr) estu specifita.
  • la SELECT kolumno en la difina demando ne povas esti kompleksa esprimo kun kolumnoj de pluraj bazaj tabeloj. Ebla solvo al ĉi tio estas uzi nestitan materiigitan vidon.
  • la SELECT listo devas enhavi ĉiujn GROUP BY kolumnoj.
  • La realigita vido ne baziĝas sur unu aŭ pluraj foraj tabeloj.
  • Se vi uzas a CHAR datumtipo en la filtrilaj kolumnoj de materiigita vidprotokolo, la signaro de la majstra retejo kaj la materiigita vido devas esti la samaj.
  • Se la realigita vido havas unu el la jenaj, tiam rapida refreŝiĝo estas subtenata nur sur konvenciaj DML-enigaĵoj kaj rektaj ŝarĝoj.
    • Materiigitaj vidoj kun MIN or MAX agregaĵoj
    • Materiigitaj vidoj kiuj havas SUM(expr) sed ne COUNT(expr)
    • Materiigitaj vidoj sen COUNT(*)

    Tia materiigita vido estas nomita nur enigebla materiigita vido.

  • Realigita vido kun MAX or MIN estas rapide refreŝebla post forigo aŭ miksita DML-deklaroj se ĝi ne havas a WHERE klaŭzo.
    La maksimuma/min rapida refreŝiĝo post forigo aŭ miksita DML ne havas la saman konduton kiel la nur-enmeta kazo. Ĝi forigas kaj rekalkulas la maksimumajn / minajn valorojn por la tuŝitaj grupoj. Vi devas esti konscia pri ĝia agado efiko.
  • Materiigitaj vidoj kun nomitaj vidoj aŭ subdemandoj en la FROM klaŭzo povas esti rapide refreŝigita kondiĉe ke la vidoj povas esti tute kunfanditaj. Por informoj pri kiuj vidoj kunfandiĝos, vidu Oracle Database SQL Language Referenco.
  • Se ne ekzistas eksteraj kuniĝoj, vi eble havas arbitrajn elektojn kaj aliĝojn en la WHERE klaŭzo.
  • Realigitaj entutaj vidoj kun eksteraj kuniĝoj estas rapide refreŝeblaj post konvencia DML kaj rektaj ŝarĝoj, kondiĉe ke nur la ekstera tablo estis modifita. Ankaŭ, unikaj limoj devas ekzisti sur la kunigaj kolumnoj de la interna kunigotabelo. Se estas eksteraj kuniĝoj, ĉiuj kuniĝoj devas esti konektitaj per ANDs kaj devas uzi la egalecon (=) operatoro.
  • Por realigitaj vidoj kun CUBE, ROLLUP, grupigaj aroj aŭ kunligado de ili, validas la sekvaj limigoj:
    • la SELECT listo devus enhavi grupigan distingilon kiu povas aŭ esti a GROUPING_ID funkcio sur ĉiuj GROUP BY esprimoj aŭ GROUPING funkcioj unu por ĉiu GROUP BY esprimo. Ekzemple, se la GROUP BY klaŭzo de la materiigita vido estas "GROUP BY CUBE(a, b)", tiam la SELECT listo devus enhavi aŭ "GROUPING_ID(a, b)» aŭ «GROUPING(a) AND GROUPING(b)» por ke la materiigita vido estu rapide refreŝigebla.
    • GROUP BY ne devus rezultigi iujn duoblajn grupiĝojn. Ekzemple, "GROUP BY a, ROLLUP(a, b)" ne estas rapide refreŝebla ĉar ĝi rezultigas duplikatajn grupiĝojn "(a), (a, b), AND (a)".

5.3.8.7 Limigoj pri Rapida Refreŝiĝo pri Materiigitaj Vidoj kun UNION ALL

Materiigitaj vidoj kun la UNION ALL agordi operatoran subtenon la REFRESH FAST opcio se la sekvaj kondiĉoj estas kontentigitaj:

  • La difina demando devas havi la UNION ALL operatoro ĉe la supera nivelo.

    la UNION ALL operatoro ne povas esti enigita en subdemando, kun unu escepto: La UNION ALL povas esti en subdemando en la FROM klaŭzo kondiĉe ke la difina demando estas de la formo SELECT * FROM (vido aŭ subdemando kun UNION ALL) kiel en la sekva ekzemplo:

    KREU VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM klientoj c WHERE c.cust_last_name = 'Smith' UNION ĈIUJ SELECT c.rowid crid, c.cust_id, 3 umarker FROM klientoj c WHERE c.cust_last_name 'Jones'); KREU MATERIALIZITAN VIDON unionall_inside_view_mv REFRESHIGU RAPIDE LAŬ PETO KIEL ELEKTU * DE view_with_unionall;
    

    Notu ke la vido view_with_unionall kontentigas la postulojn por rapida refreŝiĝo.

  • Ĉiu demandobloko en la UNION ALL demando devas kontentigi la postulojn de rapida refreŝebla realigita vido kun agregaĵoj aŭ rapida refreshable realigita vido kun kuniĝoj.

    La taŭgaj materiigitaj vidprogramoj devas esti kreitaj sur la tabeloj laŭbezone por la responda speco de rapide refreŝigebla materiigita vido.
    Notu, ke la Orakolo-Datumbazo ankaŭ permesas la specialan kazon de ununura tablo materiigita vido kun kuniĝoj nur kondiĉe la ROWID kolumno estis inkluzivita en la SELECT listo kaj en la materiigita vido protokolo. Ĉi tio montriĝas en la difina demando de la vido view_with_unionall.

  • la SELECT listo de ĉiu demando devas inkluzivi a UNION ALL markilo, kaj la UNION ALL kolumno devas havi klaran konstantan nombran aŭ ĉenvaloron en ĉiu UNION ALL branĉo. Plue, la markilokolono devas aperi en la sama orda pozicio en la SELECT listo de ĉiu demanda bloko. Vidu "UNIO ĈIUJ Markilo kaj Demando Reskribi» por pliaj informoj pri UNION ALL markiloj.
  • Iuj funkcioj kiel eksteraj kuniĝoj, nur enmetataj entutaj materiigitaj viddemandoj kaj foraj tabeloj ne estas subtenataj por materiigitaj vidoj kun UNION ALL. Notu, tamen, ke realigitaj vidoj uzataj en reproduktado, kiuj ne enhavas kuniĝojn aŭ agregaĵojn, povas esti rapide refreŝigitaj kiam UNION ALL aŭ foraj tabloj estas uzataj.
  • La kongrua inicialiga parametro devas esti agordita al 9.2.0 aŭ pli alta por krei rapide refreŝigeblan materiigitan vidon kun UNION ALL.

Mi ne volas ofendi la adorantojn de Oracle, sed juĝante laŭ ilia listo de limigoj, ŝajnas, ke ĉi tiu mekanismo estis skribita ne en la ĝenerala kazo, uzante ian modelon, sed de miloj da indianoj, kie ĉiuj ricevis la ŝancon skribu sian propran branĉon, kaj ĉiu el ili faris, kion li povis, kaj faris. Uzi ĉi tiun mekanismon por reala logiko estas kiel promeni tra minkampo. Vi povas akiri minon iam ajn trafante unu el la neevidentaj limigoj. Kiel ĝi funkcias ankaŭ estas aparta demando, sed ĝi estas ekster la amplekso de ĉi tiu artikolo.

Microsoft SQL Server

Pliaj Postuloj

Krom la SET-opcioj kaj determinismaj funkciopostuloj, la sekvaj postuloj devas esti plenumitaj:

  • La uzanto kiu ekzekutas CREATE INDEX devas esti la posedanto de la vido.
  • Kiam vi kreas la indekson, la IGNORE_DUP_KEY opcio devas esti agordita al OFF (la defaŭlta agordo).
  • Tabeloj devas esti referencitaj per dupartaj nomoj, skemo.tabelnomo en la viddifino.
  • Uzant-difinitaj funkcioj referencitaj en la vido devas esti kreitaj uzante la WITH SCHEMABINDING elekto.
  • Ĉiuj uzant-difinitaj funkcioj referencitaj en la vido devas esti referencitaj per dupartaj nomoj, ..
  • La datuma alirposedaĵo de uzant-difinita funkcio devas esti NO SQL, kaj ekstera alirposedaĵo devas esti NO.
  • Komunlingva rultempa (CLR) funkcioj povas aperi en la elekta listo de la vido, sed ne povas esti parto de la difino de la amasigita indeksa ŝlosilo. CLR-funkcioj ne povas aperi en la WHERE-frazo de la vido aŭ la ON-frazo de JOIN-operacio en la vido.
  • CLR-funkcioj kaj metodoj de CLR uzant-difinitaj tipoj uzataj en la vidodifino devas havi la trajtojn agordita kiel montrite en la sekva tabelo.

    propraĵo
    noto

    DETERMINISTA = VERA
    Devas esti deklarita eksplicite kiel atributo de la metodo de Microsoft .NET Framework.

    PRECISE = VERA
    Devas esti deklarita eksplicite kiel atributo de la metodo .NET Framework.

    ALIRO DE DATUMO = NE SQL
    Determinite fiksante DataAccess-atributon al DataAccessKind.None kaj SystemDataAccess-atributon al SystemDataAccessKind.None.

    EKSTERA ALIRO = NE
    Ĉi tiu posedaĵo defaŭlte al NO por CLR-rutinoj.

  • La vido devas esti kreita uzante la WITH SCHEMABINDING elekto.
  • La vido devas referenci nur bazajn tabelojn kiuj estas en la sama datumbazo kiel la vido. La vido ne povas referenci aliajn vidojn.
  • La SELECT deklaro en la viddifino ne devas enhavi la sekvajn Transact-SQL-elementojn:

    COUNT
    ROWSET-funkcioj (OPENDATASOURCE, OPENQUERY, OPENROWSET, KAJ OPENXML)
    OUTER aliĝas (LEFT, RIGHTFULL)

    Derivita tabelo (difinita per specifo de a SELECT aserto en la FROM subfrazo)
    Mem-kuniĝoj
    Specifante kolumnojn per uzado SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARPAVG
    Ofta tabelesprimo (CTE)

    kaleŝego1, teksto, nteksto, bildo, XMLdosierfluo kolumnoj
    Subdemandado
    OVER klaŭzo, kiu inkluzivas rangojn aŭ entutajn fenestrajn funkciojn

    Plentekstaj predikatoj (CONTAINS, FREETEXT)
    SUM funkcio kiu referencas al nulebla esprimo
    ORDER BY

    CLR uzant-difinita entuta funkcio
    TOP
    CUBE, ROLLUPGROUPING SETS operatoroj

    MIN, MAX
    UNION, EXCEPTINTERSECT operatoroj
    TABLESAMPLE

    Tabelvariabloj
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Maldensaj kolonaroj
    Enliniaj (TVF) aŭ mult-deklaraj tabel-valoraj funkcioj (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 La indeksita vido povas enhavi kaleŝego kolumnoj; tamen tiaj kolumnoj ne povas esti inkluzivitaj en la amasigita indeksa ŝlosilo.

  • If GROUP BY ĉeestas, la VIEW-difino devas enhavi COUNT_BIG(*) kaj ne devas enhavi HAVING. tiuj GROUP BY restriktoj estas aplikeblaj nur al la indeksita vidodifino. Demando povas uzi indeksitan vidon en sia ekzekutplano eĉ se ĝi ne kontentigas tiujn GROUP BY restriktoj.
  • Se la viddifino enhavas a GROUP BY klaŭzo, la ŝlosilo de la unika amasigita indekso povas referenci nur la kolumnojn specifitajn en la GROUP BY klaŭzo.

Estas klare ĉi tie, ke la indianoj ne estis implikitaj, ĉar ili decidis fari ĝin laŭ la skemo "ni faros malmulton, sed bone." Tio estas, ili havas pli da minoj sur la kampo, sed ilia loko estas pli travidebla. La plej seniluziiga afero estas ĉi tiu limigo:

La vido devas referenci nur bazajn tabelojn kiuj estas en la sama datumbazo kiel la vido. La vido ne povas referenci aliajn vidojn.

En nia terminologio, tio signifas, ke funkcio ne povas aliri alian materiigitan funkcion. Ĉi tio tranĉas ĉian ideologion en la burĝono.
Ankaŭ ĉi tiu limigo (kaj plue en la teksto) multe reduktas la uzkazojn:

La SELECT deklaro en la viddifino ne devas enhavi la sekvajn Transact-SQL-elementojn:

COUNT
ROWSET-funkcioj (OPENDATASOURCE, OPENQUERY, OPENROWSET, KAJ OPENXML)
OUTER aliĝas (LEFT, RIGHTFULL)

Derivita tabelo (difinita per specifo de a SELECT aserto en la FROM subfrazo)
Mem-kuniĝoj
Specifante kolumnojn per uzado SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARPAVG
Ofta tabelesprimo (CTE)

kaleŝego1, teksto, nteksto, bildo, XMLdosierfluo kolumnoj
Subdemandado
OVER klaŭzo, kiu inkluzivas rangojn aŭ entutajn fenestrajn funkciojn

Plentekstaj predikatoj (CONTAINS, FREETEXT)
SUM funkcio kiu referencas al nulebla esprimo
ORDER BY

CLR uzant-difinita entuta funkcio
TOP
CUBE, ROLLUPGROUPING SETS operatoroj

MIN, MAX
UNION, EXCEPTINTERSECT operatoroj
TABLESAMPLE

Tabelvariabloj
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Maldensaj kolonaroj
Enliniaj (TVF) aŭ mult-deklaraj tabel-valoraj funkcioj (MSTVF)
OFFSET

CHECKSUM_AGG

EKSTERAJ UNIĜOJ, UNIO, MENDO DE kaj aliaj estas malpermesitaj. Eble estis pli facile specifi kio povus esti uzata prefere ol kio ne povus esti uzata. La listo verŝajne estus multe pli mallonga.

Por resumi: grandega aro da restriktoj en ĉiu (ni notu komerca) DBMS kontraŭ neniu (krom unu logika, ne teknika) en LGPL-teknologio. Tamen, oni devas rimarki, ke efektivigi ĉi tiun mekanismon en interrilata logiko estas iom pli malfacila ol en la priskribita funkcia logiko.

Реализация

Kiel ĝi funkcias? PostgreSQL estas uzata kiel "virtuala maŝino". Estas kompleksa algoritmo ene, kiu konstruas demandojn. Jen fonto. Kaj ne estas nur granda aro da heŭristiko kun amaso da se. Do, se vi havas kelkajn monatojn por studi, vi povas provi kompreni arkitekturon.

Ĉu ĝi funkcias efike? Sufiĉe efika. Bedaŭrinde, ĉi tio estas malfacile pruvebla. Mi nur povas diri, ke se vi konsideras la milojn da petoj, kiuj ekzistas en grandaj aplikoj, tiam averaĝe ili estas pli efikaj ol tiuj de bona programisto. Bonega SQL-programisto povas skribi ajnan demandon pli efike, sed kun mil demandoj li simple ne havos la instigon aŭ tempon por fari ĝin. La nura afero, kiun mi nun povas citi kiel pruvon de efikeco, estas, ke pluraj projektoj funkcias sur la platformo konstruita sur ĉi tiu DBMS. ERP-sistemoj, kiuj havas milojn da malsamaj MATERIALIZITAJ funkcioj, kun miloj da uzantoj kaj terabajtaj datumbazoj kun centoj da milionoj da rekordoj kurantaj sur regula du-procesora servilo. Tamen ĉiu povas kontroli/refuti la efikecon per elŝuto platformo kaj PostgreSQL, ŝaltante registrante SQL-demandojn kaj provante ŝanĝi la logikon kaj datumojn tie.

En la sekvaj artikoloj, mi ankaŭ parolos pri kiel vi povas agordi limigojn pri funkcioj, labori kun ŝanĝaj sesioj kaj multe pli.

fonto: www.habr.com

Aldoni komenton