Equilibrar escriptures i lectures a la base de dades

Equilibrar escriptures i lectures a la base de dades
A l’anterior article Vaig descriure el concepte i la implementació d'una base de dades construïda sobre la base de funcions, en lloc de taules i camps com en les bases de dades relacionals. Va proporcionar molts exemples que mostren els avantatges d'aquest enfocament respecte al clàssic. Molts els van trobar no prou convincents.

En aquest article, mostraré com aquest concepte us permet equilibrar de manera ràpida i còmoda l'escriptura i la lectura a la base de dades sense cap canvi en la lògica de funcionament. S'ha intentat implementar una funcionalitat similar als SGBD comercials moderns (en particular, Oracle i Microsoft SQL Server). Al final de l'article mostraré que el que van fer, per dir-ho suaument, no va funcionar gaire bé.

Descripció

Com abans, per a una millor comprensió començaré la descripció amb exemples. Suposem que hem d'implementar una lògica que retorni una llista de departaments amb el nombre d'empleats que hi tenen i el seu salari total.

En una base de dades funcional es veuria així:

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 complexitat d'executar aquesta consulta en qualsevol SGBD serà equivalent a O (nombre d'empleats)perquè aquest càlcul requereix escanejar tota la taula d'empleats i després agrupar-los per departament. També hi haurà un petit complement (creiem que hi ha molts més empleats que departaments) en funció del pla escollit O (nombre de registre d'empleats) o O (nombre de departaments) per agrupar i així successivament.

Està clar que la sobrecàrrega d'execució pot ser diferent en diferents SGBD, però la complexitat no canviarà de cap manera.

En la implementació proposada, el SGBD funcional generarà una subconsulta que calcularà els valors requerits per al departament, i després realitzarà un JOIN amb la taula del departament per obtenir el nom. Tanmateix, per a cada funció, en declarar, és possible establir un marcador especial MATERIALITZAT. El sistema crearà automàticament un camp corresponent per a cada funció. Quan es canvia el valor d'una funció, el valor del camp també canviarà en la mateixa transacció. En accedir a aquesta funció, s'accedirà al camp precalculat.

En particular, si configureu MATERIALIZED per a funcions comptarEmpleats и SalarySum, llavors s'afegiran dos camps a la taula amb la llista de departaments, que emmagatzemarà el nombre d'empleats i el seu salari total. Sempre que es produeixi un canvi en els empleats, els seus sous o les afiliacions al departament, el sistema canviarà automàticament els valors d'aquests camps. La consulta anterior accedirà directament a aquests camps i s'executarà a O (nombre de departaments).

Quines són les restriccions? Només una cosa: aquesta funció ha de tenir un nombre finit de valors d'entrada per als quals es defineix el seu valor. En cas contrari, serà impossible construir una taula que emmagatzemi tots els seus valors, ja que no hi pot haver una taula amb un nombre infinit de files.

Exemple:

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

Aquesta funció es defineix per a un nombre infinit de valors de N (per exemple, qualsevol valor negatiu és adequat). Per tant, no hi pots posar MATERIALITZAT. Per tant, aquesta és una limitació lògica, no tècnica (és a dir, no perquè no la poguéssim implementar). En cas contrari, no hi ha restriccions. Podeu utilitzar agrupacions, ordenació, AND i OR, PARTICIÓ, recursivitat, etc.

Per exemple, al problema 2.2 de l'article anterior, podeu posar MATERIALITZAT en ambdues funcions:

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;

El propi sistema crearà una taula amb tecles de tipus Client, Producte и ENTER, hi afegirà dos camps i actualitzarà els valors dels camps amb qualsevol canvi. Quan es facin més crides a aquestes funcions, no es calcularan, sinó que es llegiran els valors dels camps corresponents.

Mitjançant aquest mecanisme, podeu, per exemple, desfer-vos de les recursions (CTE) a les consultes. En particular, considereu els grups que formen un arbre mitjançant la relació fill/pare (cada grup té un enllaç al seu pare):

parent = DATA Group (Group);

En una base de dades funcional, la lògica de recursivitat es pot especificar de la següent manera:

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;

Ja que per a la funció isParent està marcat MATERIALITZAT, llavors es crearà una taula amb dues claus (grups) en la qual el camp isParent només serà certa si la primera clau és una filla de la segona. El nombre d'entrades d'aquesta taula serà igual al nombre de grups multiplicat per la profunditat mitjana de l'arbre. Si necessiteu, per exemple, comptar el nombre de descendents d'un grup determinat, podeu utilitzar aquesta funció:

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

No hi haurà CTE a la consulta SQL. En canvi hi haurà un simple GROUP BY.

Amb aquest mecanisme, també podeu desnormalitzar fàcilment la base de dades si cal:

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

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

En cridar una funció data per a la línia de comanda, el camp per al qual hi ha un índex es llegirà de la taula amb línies de comanda. Quan canvia la data de la comanda, el propi sistema tornarà a calcular automàticament la data desnormalitzada a la línia.

Avantatges

Per a què serveix tot aquest mecanisme? En els SGBD clàssics, sense reescriure les consultes, un desenvolupador o DBA només pot canviar índexs, determinar estadístiques i dir al planificador de consultes com executar-les (i els HINT només estan disponibles als SGBD comercials). Per molt que ho intentin, no podran completar la primera consulta de l'article a O (nombre de departaments) sense canviar les consultes ni afegir activadors. En l'esquema proposat, en l'etapa de desenvolupament no cal pensar en l'estructura d'emmagatzematge de dades i quines agregacions utilitzar. Tot això es pot canviar fàcilment sobre la marxa, directament en funcionament.

A la pràctica es veu així. Algunes persones desenvolupen la lògica directament en funció de la tasca a realitzar. No entenen els algorismes i la seva complexitat, ni els plans d'execució, ni els tipus d'unions, ni cap altre component tècnic. Aquestes persones són més analistes de negocis que desenvolupadors. Després, tot això passa a les proves o al funcionament. Permet el registre de consultes de llarga durada. Quan es detecta una consulta llarga, altres persones (més tècniques, essencialment DBA) decideixen habilitar MATERIALIZED en alguna funció intermèdia. Això alenteix una mica l'enregistrament (ja que requereix actualitzar un camp addicional a la transacció). Tanmateix, no només aquesta consulta s'accelera significativament, sinó també totes les altres que utilitzen aquesta funció. Al mateix temps, decidir quina funció es materialitzarà és relativament fàcil. Dos paràmetres principals: el nombre de valors d'entrada possibles (és el nombre de registres que hi haurà a la taula corresponent) i la freqüència amb què s'utilitza en altres funcions.

Anàlegs

Els SGBD comercials moderns tenen mecanismes similars: VISUALITZACIÓ MATERIALITZADA amb ACTUALITZACIÓ RÀPIDA (Oracle) i VISUALITZACIÓ INDEXADA (Microsoft SQL Server). A PostgreSQL, MATERIALIZED VIEW no es pot actualitzar en una transacció, sinó només a petició (i fins i tot amb restriccions molt estrictes), per la qual cosa no ho tenim en compte. Però tenen diversos problemes que limiten significativament el seu ús.

En primer lloc, només podeu habilitar la materialització si ja heu creat una VISTA normal. En cas contrari, haureu de reescriure les sol·licituds restants per accedir a la vista de nova creació per utilitzar aquesta materialització. O deixar-ho tot tal com està, però almenys serà ineficaç si hi ha certes dades ja precalculades, però moltes consultes no sempre les fan servir, sinó que les tornen a calcular.

En segon lloc, tenen un gran nombre de restriccions:

Oracle

5.3.8.4 Restriccions generals sobre l'actualització ràpida

La consulta definidora de la vista materialitzada està restringida de la següent manera:

  • La vista materialitzada no ha de contenir referències a expressions no repetides com SYSDATE i ROWNUM.
  • La vista materialitzada no ha de contenir referències a RAW or LONG RAW tipus de dades.
  • No pot contenir a SELECT subconsulta de llista.
  • No pot contenir funcions analítiques (per exemple, RANK) Al SELECT clàusula.
  • No pot fer referència a una taula en què an XMLIndex es defineix l'índex.
  • No pot contenir a MODEL clàusula.
  • No pot contenir a HAVING clàusula amb una subconsulta.
  • No pot contenir consultes imbricades que tinguin ANY, ALL, O NOT EXISTS.
  • No pot contenir a [START WITH …] CONNECT BY clàusula.
  • No pot contenir diverses taules de detalls en llocs diferents.
  • ON COMMIT Les vistes materialitzades no poden tenir taules de detalls remotes.
  • Les vistes materialitzades imbricades han de tenir una unió o un agregat.
  • Visualitzacions d'unió materialitzades i vistes agregades materialitzades amb a GROUP BY la clàusula no pot seleccionar-se d'una taula organitzada per índex.

5.3.8.5 Restriccions a l'actualització ràpida en visualitzacions materialitzades només amb unions

La definició de consultes per a visualitzacions materialitzades només amb unions i sense agregats té les restriccions següents sobre l'actualització ràpida:

  • Totes les restriccions de «Restriccions generals sobre l'actualització ràpida".
  • No poden tenir GROUP BY clàusules o agregats.
  • Fileres de totes les taules del FROM ha d'aparèixer a la llista SELECT llista de la consulta.
  • Els registres de visualització materialitzats han d'existir amb filades per a totes les taules base del fitxer FROM llista de la consulta.
  • No podeu crear una vista materialitzada que es pugui actualitzar ràpidament a partir de diverses taules amb unions simples que incloguin una columna de tipus d'objecte a la SELECT declaració.

A més, el mètode d'actualització que trieu no serà òptimment eficient si:

  • La consulta definidora utilitza una unió externa que es comporta com una unió interna. Si la consulta definidora conté una unió d'aquest tipus, penseu a reescriure la consulta definidora perquè contingui una unió interna.
  • El SELECT La llista de la vista materialitzada conté expressions en columnes de diverses taules.

5.3.8.6 Restriccions a l'actualització ràpida en vistes materialitzades amb agregats

La definició de consultes per a visualitzacions materialitzades amb agregats o unions té les restriccions següents sobre l'actualització ràpida:

Ambdós admeten l'actualització ràpida ON COMMIT i ON DEMAND visualitzacions materialitzades, però s'apliquen les restriccions següents:

  • Totes les taules de la vista materialitzada han de tenir registres de visualització materialitzada i els registres de visualització materialitzada han de:
    • Conté totes les columnes de la taula a la qual es fa referència a la vista materialitzada.
    • Especifica amb ROWID i INCLUDING NEW VALUES.
    • especificar el SEQUENCE clàusula si s'espera que la taula tingui una combinació d'insercions/càrregues directes, supressions i actualitzacions.

  • Només SUM, COUNT, AVG, STDDEV, VARIANCE, MIN i MAX són compatibles per a una actualització ràpida.
  • COUNT(*) s'ha d'especificar.
  • Les funcions agregades només s'han de produir com a part més externa de l'expressió. És a dir, agregats com AVG(AVG(x)) or AVG(x)+ AVG(x) no estan permesos.
  • Per a cada agregat com ara AVG(expr), el corresponent COUNT(expr) ha d'estar present. Oracle ho recomana SUM(expr) ser especificat.
  • If VARIANCE(expr) or STDDEV(expr) s'especifica, COUNT(expr) i SUM(expr) s'ha d'especificar. Oracle ho recomana SUM(expr *expr) ser especificat.
  • El SELECT La columna de la consulta definidora no pot ser una expressió complexa amb columnes de diverses taules base. Una possible solució a això és utilitzar una vista materialitzada imbricada.
  • El SELECT la llista ha de contenir-ho tot GROUP BY columnes.
  • La vista materialitzada no es basa en una o més taules remotes.
  • Si utilitzeu a CHAR tipus de dades a les columnes de filtre d'un registre de visualització materialitzada, els conjunts de caràcters del lloc mestre i la vista materialitzada han de ser els mateixos.
  • Si la visualització materialitzada té un dels següents, l'actualització ràpida només s'admet amb insercions DML convencionals i càrregues directes.
    • Vistes materialitzades amb MIN or MAX àrids
    • Vistes materialitzades que tenen SUM(expr) però no COUNT(expr)
    • Vistes materialitzades sense COUNT(*)

    Aquesta vista materialitzada s'anomena vista materialitzada només d'inserció.

  • Una visió materialitzada amb MAX or MIN es pot actualitzar ràpidament després de suprimir o barrejar declaracions DML si no té un WHERE clàusula.
    L'actualització ràpida màxima/min després de la supressió o la combinació de DML no té el mateix comportament que el cas d'inserció només. Esborra i torna a calcular els valors màxim/mínim dels grups afectats. Heu de ser conscients del seu impacte en el rendiment.
  • Visualitzacions materialitzades amb vistes o subconsultes anomenades al fitxer FROM la clàusula es pot actualitzar ràpidament sempre que les vistes es puguin combinar completament. Per obtenir informació sobre quines vistes es fusionaran, vegeu Referència del llenguatge SQL de la base de dades Oracle.
  • Si no hi ha unions externes, és possible que tingueu seleccions i unions arbitràries al fitxer WHERE clàusula.
  • Les vistes agregades materialitzades amb unions exteriors es poden actualitzar ràpidament després de les càrregues directes i DML convencionals, sempre que només s'hagi modificat la taula exterior. A més, han d'existir restriccions úniques a les columnes d'unió de la taula d'unió interna. Si hi ha unions externes, totes les unions han d'estar connectades per ANDs i ha d'utilitzar la igualtat (=) operador.
  • Per a vistes materialitzades amb CUBE, ROLLUP, conjunts d'agrupació o concatenació d'ells, s'apliquen les restriccions següents:
    • El SELECT La llista ha de contenir un distintiu d'agrupació que pot ser a GROUPING_ID funció a tots GROUP BY expressions o GROUPING funcions una per a cadascun GROUP BY expressió. Per exemple, si el GROUP BY la clàusula de la vista materialitzada és "GROUP BY CUBE(a, b)", aleshores el SELECT la llista hauria de contenir "GROUPING_ID(a, b)» o «GROUPING(a) AND GROUPING(b)» perquè la vista materialitzada es pugui actualitzar ràpidament.
    • GROUP BY no hauria de donar lloc a cap agrupació duplicada. Per exemple, "GROUP BY a, ROLLUP(a, b)" no es pot actualitzar ràpidament perquè provoca agrupacions duplicades "(a), (a, b), AND (a)".

5.3.8.7 Restriccions a l'actualització ràpida en vistes materialitzades amb UNION ALL

Vistes materialitzades amb el UNION ALL establir el suport de l'operador REFRESH FAST opció si es compleixen les condicions següents:

  • La consulta definidora ha de tenir el UNION ALL operador al primer nivell.

    El UNION ALL L'operador no es pot incrustar dins d'una subconsulta, amb una excepció: The UNION ALL pot estar en una subconsulta a FROM clàusula sempre que la consulta definidora sigui de la forma SELECT * FROM (visualitza o subconsulta amb UNION ALL) com en l'exemple següent:

    CREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM clients c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM clients c WHERE c.cust_last_name 'Jones'); CREAR UNA VISTA MATERIALITZADA unionall_inside_view_mv ACTUALITZAR RÀPIDAMENT A DEMANDA COM SELECCIONA * DES de view_with_unionall;
    

    Tingueu en compte que la vista view_with_unionall compleix els requisits per a una actualització ràpida.

  • Cada bloc de consulta del fitxer UNION ALL La consulta ha de satisfer els requisits d'una vista materialitzada que es pot actualitzar ràpidament amb agregats o una vista materialitzada que es pot actualitzar ràpidament amb enllaços.

    Els registres de visualització materialitzada adequats s'han de crear a les taules segons sigui necessari per al tipus corresponent de visualització materialitzada d'actualització ràpida.
    Tingueu en compte que la base de dades Oracle també permet el cas especial d'una vista materialitzada de taula única amb unions només sempre que el ROWID la columna s'ha inclòs a la columna SELECT llista i al registre de visualització materialitzada. Això es mostra a la consulta definidora de la vista view_with_unionall.

  • El SELECT La llista de cada consulta ha d'incloure a UNION ALL marcador, i el UNION ALL La columna ha de tenir un valor numèric o de cadena constant diferent en cadascuna UNION ALL branca. A més, la columna del marcador ha d'aparèixer a la mateixa posició ordinal al SELECT llista de cada bloc de consulta. Veure "UNION ALL Marcador i reescriptura de consultes» per a més informació sobre UNION ALL retoladors.
  • Algunes funcions, com ara les unions externes, les consultes de visualitzacions materialitzades agregades només d'inserció i les taules remotes, no s'admeten per a les visualitzacions materialitzades amb UNION ALL. Tingueu en compte, però, que les vistes materialitzades que s'utilitzen en la replicació, que no contenen unions ni agregats, es poden actualitzar ràpidament quan UNION ALL o s'utilitzen taules remotes.
  • El paràmetre d'inicialització de compatibilitat s'ha d'establir a 9.2.0 o superior per crear una visualització materialitzada que es pugui actualitzar ràpidament amb UNION ALL.

No vull ofendre els fans d'Oracle, però a jutjar per la seva llista de restriccions, sembla que aquest mecanisme no es va escriure en el cas general, utilitzant algun tipus de model, sinó per milers d'indis, on tothom tenia l'oportunitat de Escriu la seva pròpia branca, i cadascun d'ells va fer el que va poder i va fer. Utilitzar aquest mecanisme per a la lògica real és com caminar per un camp de mines. Podeu obtenir una mina en qualsevol moment tocant una de les restriccions no òbvies. Com funciona també és una qüestió a part, però està fora de l'abast d'aquest article.

Microsoft SQL Server

Requisits addicionals

A més de les opcions SET i els requisits de funció determinista, s'han de complir els requisits següents:

  • L'usuari que executa CREATE INDEX ha de ser el propietari de la vista.
  • Quan creeu l'índex, el IGNORE_DUP_KEY l'opció s'ha d'establir a OFF (la configuració predeterminada).
  • Les taules s'han de fer referència amb noms de dues parts, esquema.nom de la taula a la definició de la vista.
  • Les funcions definides per l'usuari a les quals es fa referència a la vista s'han de crear mitjançant l' WITH SCHEMABINDING opció.
  • Qualsevol funció definida per l'usuari a la qual es fa referència a la vista s'ha de fer referència amb noms de dues parts, ..
  • La propietat d'accés a les dades d'una funció definida per l'usuari ha de ser NO SQL, i la propietat d'accés extern ha de ser NO.
  • Les funcions de Common Language Runtime (CLR) poden aparèixer a la llista de selecció de la vista, però no poden formar part de la definició de la clau d'índex agrupat. Les funcions CLR no poden aparèixer a la clàusula WHERE de la vista o la clàusula ON d'una operació JOIN a la vista.
  • Les funcions i mètodes CLR dels tipus definits per l'usuari CLR utilitzats a la definició de la vista han de tenir les propietats establertes tal com es mostra a la taula següent.

    Propietat
    Nota

    DETERMINÍSTIC = CERT
    S'ha de declarar explícitament com a atribut del mètode Microsoft .NET Framework.

    PRECIS = CERT
    S'ha de declarar explícitament com a atribut del mètode .NET Framework.

    ACCÉS A DADES = NO SQL
    Es determina establint l'atribut DataAccess a DataAccessKind.None i l'atribut SystemDataAccess a SystemDataAccessKind.None.

    ACCÉS EXTERIOR = NO
    Aquesta propietat per defecte és NO per a les rutines CLR.

  • La vista s'ha de crear mitjançant l' WITH SCHEMABINDING opció.
  • La vista només ha de fer referència a taules base que es troben a la mateixa base de dades que la vista. La vista no pot fer referència a altres vistes.
  • La sentència SELECT de la definició de vista no ha de contenir els elements Transact-SQL següents:

    COUNT
    funcions ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, I OPENXML)
    OUTER s'uneix (LEFT, RIGHT, O FULL)

    Taula derivada (definida especificant a SELECT declaració al FROM clàusula)
    Auto-unions
    Especificació de columnes utilitzant SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, O AVG
    Expressió de taula comuna (CTE)

    flotador1, text, ntext, imatge, XML, O flux de fitxers columnes
    Subconsulta
    OVER clàusula, que inclou funcions de finestra de classificació o agregació

    Predicats de text complet (CONTAINS, FREETEXT)
    SUM funció que fa referència a una expressió nul·la
    ORDER BY

    Funció d'agregació CLR definida per l'usuari
    TOP
    CUBE, ROLLUP, O GROUPING SETS operadors

    MIN, MAX
    UNION, EXCEPT, O INTERSECT operadors
    TABLESAMPLE

    Variables de taula
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Conjunts de columnes dispersos
    Funcions en línia (TVF) o multi-instruccions amb valors de taula (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 La vista indexada pot contenir flotador columnes; tanmateix, aquestes columnes no es poden incloure a la clau d'índex agrupat.

  • If GROUP BY està present, la definició VIEW ha de contenir COUNT_BIG(*) i no ha de contenir HAVING. Aquests GROUP BY les restriccions només s'apliquen a la definició de la vista indexada. Una consulta pot utilitzar una vista indexada en el seu pla d'execució encara que no les compleixi GROUP BY restriccions
  • Si la definició de la vista conté a GROUP BY clàusula, la clau de l'índex agrupat únic només pot fer referència a les columnes especificades a la clàusula GROUP BY clàusula.

Aquí està clar que els indis no hi van participar, ja que van decidir fer-ho d'acord amb l'esquema “no farem poc, però bé”. És a dir, tenen més mines al camp, però la seva ubicació és més transparent. El més decebedor és aquesta limitació:

La vista només ha de fer referència a taules base que es troben a la mateixa base de dades que la vista. La vista no pot fer referència a altres vistes.

En la nostra terminologia, això significa que una funció no pot accedir a una altra funció materialitzada. Això retalla tota ideologia de sobte.
A més, aquesta limitació (i més enllà en el text) redueix molt els casos d'ús:

La sentència SELECT de la definició de vista no ha de contenir els elements Transact-SQL següents:

COUNT
funcions ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, I OPENXML)
OUTER s'uneix (LEFT, RIGHT, O FULL)

Taula derivada (definida especificant a SELECT declaració al FROM clàusula)
Auto-unions
Especificació de columnes utilitzant SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARP, O AVG
Expressió de taula comuna (CTE)

flotador1, text, ntext, imatge, XML, O flux de fitxers columnes
Subconsulta
OVER clàusula, que inclou funcions de finestra de classificació o agregació

Predicats de text complet (CONTAINS, FREETEXT)
SUM funció que fa referència a una expressió nul·la
ORDER BY

Funció d'agregació CLR definida per l'usuari
TOP
CUBE, ROLLUP, O GROUPING SETS operadors

MIN, MAX
UNION, EXCEPT, O INTERSECT operadors
TABLESAMPLE

Variables de taula
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Conjunts de columnes dispersos
Funcions en línia (TVF) o multi-instruccions amb valors de taula (MSTVF)
OFFSET

CHECKSUM_AGG

Queden prohibides les JORNADES EXTERIORS, UNION, ORDER BY i altres. Podria haver estat més fàcil especificar què es podria utilitzar en lloc de què no es podria utilitzar. La llista probablement seria molt més petita.

En resum: un gran conjunt de restriccions en tots els SGBD (anotem comercials) enfront de cap (a excepció d'un lògic, no tècnic) en tecnologia LGPL. Tanmateix, cal assenyalar que la implementació d'aquest mecanisme en la lògica relacional és una mica més difícil que en la lògica funcional descrita.

Implementació

Com funciona? PostgreSQL s'utilitza com a "màquina virtual". Hi ha un algorisme complex a l'interior que crea consultes. Aquí font. I no només hi ha un gran conjunt d'heurístiques amb un munt d'if. Per tant, si teniu un parell de mesos per estudiar, podeu intentar entendre l'arquitectura.

Funciona eficaçment? Bastant efectiu. Malauradament, això és difícil de demostrar. Només puc dir que si es tenen en compte els milers de consultes que hi ha a les grans aplicacions, de mitjana són més eficients que les d'un bon desenvolupador. Un excel·lent programador SQL pot escriure qualsevol consulta de manera més eficient, però amb mil consultes simplement no tindrà la motivació ni el temps per fer-ho. L'únic que ara puc citar com a prova d'eficàcia és que diversos projectes estan treballant a la plataforma construïda sobre aquest SGBD. Sistemes ERP, que tenen milers de funcions MATERIALITZADES diferents, amb milers d'usuaris i bases de dades de terabytes amb centenars de milions de registres que s'executen en un servidor normal de dos processadors. No obstant això, qualsevol pot comprovar/refutar l'eficàcia mitjançant la descàrrega plataforma i PostgreSQL, encenent registrant consultes SQL i intentant canviar-hi la lògica i les dades.

En els articles següents, també parlaré de com podeu establir restriccions a les funcions, treballar amb sessions de canvi i molt més.

Font: www.habr.com

Afegeix comentari