
En el anterior He describí la concepción y la implementación de una base de datos construida en función de funciones, no de tablas y campos como en las bases de datos relacionales. Se presentaron numerosos ejemplos que mostraban las ventajas de este enfoque en comparación con el clásico. Muchos los consideraron insuficientemente convincentes.
En este artículo, mostraré cómo tal concepción permite equilibrar rápida y cómodamente la escritura y la lectura en la base de datos sin ningún cambio en la lógica de funcionamiento. Funcionalidades similares han intentado implementarse en los sistemas de gestión de bases de datos comerciales modernos (en particular, Oracle y Microsoft SQL Server). Al final del artículo mostraré que lo que lograron no es muy satisfactorio, por decirlo de manera suave.
Descripción
Al igual que antes, para una mejor comprensión comenzaré la descripción con ejemplos. Supongamos que necesitamos implementar la lógica que retornará una lista de departamentos con el número de empleados en ellos y su salario total.
En la base de datos funcional, esto se vería de la siguiente manera:
CLASS Departamento ‘Departamento’;
name ‘Nombre’ = DATA STRING[100] (Departamento);
CLASS Employee 'Empleado';
department 'Departamento' = DATA Department (Employee);
salary 'Salario' = DATA NUMERIC[10,2] (Employee);
countEmployees 'Número de empleados' (Department d) =
AGRUPAR SUMA 1 SI departamento(Empleado e) = d;
salarySum 'Salario total' (Department d) =
AGRUPAR SUM salary(Empleado e) SI departamento(e) = d;
SELECT name(Department d), countEmployees(d), salarySum(d);
La complejidad de ejecutar esta consulta en cualquier SGBD será equivalente a O(número de empleados), ya que para este cálculo se debe escanear toda la tabla de empleados y luego agruparlos por departamento. También habrá un pequeño suplemento (considerando que hay muchos más empleados que departamentos) dependiendo del plan elegido. O(log número de empleados) o O(número de departamentos) para la agrupación y otros aspectos.
Es evidente que los costos de ejecución pueden variar entre diferentes SGBD, pero la complejidad no cambiará de ninguna manera.
En la implementación propuesta, la base de datos funcional formará una subconsulta que calculará los valores necesarios por departamento y luego realizará un JOIN con la tabla de departamentos para obtener el nombre. Sin embargo, al declarar cada función, hay la posibilidad de establecer un marcador especial MATERIALIZED. El sistema creará automáticamente el campo correspondiente para cada una de estas funciones. Al cambiar el valor de la función, el campo también cambiará en la misma transacción. Al acceder a esta función, se hará referencia al campo ya calculado.
En particular, si se establece MATERIALIZED para las funciones conteoEmpleados y sumaSalarial, entonces se agregarán dos campos a la tabla con la lista de departamentos, donde se almacenará la cantidad de empleados y su salario total. Ante cualquier cambio en los empleados, sus salarios o su pertenencia a departamentos, el sistema actualizará automáticamente los valores de estos campos. La consulta mencionada anteriormente se dirigirá directamente a estos campos y se ejecutará en O(número de departamentos).
¿Cuáles son las restricciones? Solo una: esta función debe tener un número finito de entradas para las cuales su valor está definido. De lo contrario, no será posible construir una tabla que almacene todos sus valores, ya que no puede haber una tabla con un número infinito de filas.
Ejemplo:
employeesCount 'Número de empleados con salario > N' (Departamento d, NUMERIC[10,2] N) =
SUMA GRUPO salario(Empleado e) SI departamento(e) = d Y salario(e) > N;
Esta función está definida para un número infinito de valores del número N (por ejemplo, cualquier valor negativo es válido). Por lo tanto, no se le puede aplicar MATERIALIZED. Así, esta es una restricción lógica y no técnica (es decir, no porque no hayamos podido implementarla). Aparte de eso, no hay restricciones. Se pueden usar agrupaciones, ordenamientos, AND y OR, PARTITION, recursiones, etc.
Por ejemplo, en el ejercicio 2.2 del artículo anterior se puede aplicar MATERIALIZED a ambas funciones:
comprado 'Comprado' (Cliente c, Producto p, ENTERO y) =
SUMA DE GRUPO suma(Detalle d) SI
cliente(pedido(d)) = c Y
producto(d) = p Y
extraerAño(fecha(pedido(d))) = y MATERIALIZADO;
calificación 'Calificación' (Cliente c, Producto p, ENTERO y) =
PARTICIÓN SUMA 1 ORDEN DESC comprado(c, p, y), p POR c, y MATERIALIZADO;
SELECCIONAR nombreContacto(Cliente c), nombre(Producto p) DONDE calificación(c, p, 1997) < 3;
El sistema creará automáticamente una tabla con claves de tipo Cliente, Producto y ENTERO, añadirá dos campos y actualizará los valores de esos campos con cualquier cambio. En futuras referencias a estas funciones, no se calcularán, sino que se leerán los valores de los campos correspondientes.
Con este mecanismo, se puede, por ejemplo, prescindir de recursiones (CTE) en las consultas. En particular, consideremos grupos que forman un árbol mediante la relación child/parent (cada grupo tiene un enlace a su padre):
parent = DATA Group (Grupo);
En la base de datos funcional, se puede definir la lógica de las recursiones de la siguiente manera:
nivel (Grupo hijo, Grupo padre) = RECURSION 1l SI hijo ES Grupo Y padre == hijo
PASO 2l SI padre == padre($parent);
esPadre (Grupo hijo, Grupo padre) = VERDADERO SI nivel(hijo, padre) MATERIALIZADO;
Dado que para la función esPadre se ha asignado MATERIALIZED, se creará una tabla con dos claves (grupos), donde el campo esPadre será verdadero solo si la primera clave es un descendiente de la segunda. La cantidad de registros en esta tabla será igual al número de grupos multiplicado por la profundidad media del árbol. Si se necesita, por ejemplo, contar el número de descendientes de un grupo específico, se puede referirse a esta función:
childrenCount (Grupo g) = SUMA DEL GRUPO 1 SI esPadre(Grupo hijo, g);
No habrá CTE en la consulta SQL. En su lugar, habrá un simple GROUP BY.
A través de este mecanismo también se puede realizar fácilmente la desnormalización de la base de datos si es necesario:
CLASS Pedido 'Pedido';
fecha 'Fecha' = DATA DATE (Orden);
CLASE OrderDetail 'Línea de pedido';
pedido 'Pedido' = DATOS Order (OrderDetail);
fecha 'Fecha' (OrderDetail d) = fecha(order(d)) ÍNDICE MATERIALIZADO;
Al llamar a la función Muestra la fecha y hora actuales del sistema. para la línea de pedido, se realizará una lectura de la tabla con las líneas de pedidos en el campo que tiene un índice. Cuando se cambie la fecha del pedido, el sistema recalculará automáticamente la fecha desnormalizada en la línea.
Ventajas
¿Para qué se necesita todo este mecanismo? En las bases de datos tradicionales, sin reescribir consultas, un desarrollador o DBA solo puede modificar índices, establecer estadísticas y sugerir al planificador de consultas cómo ejecutarlas (y las HINTs solo están disponibles en bases de datos comerciales). Por mucho esfuerzo que realicen, no podrán ejecutar la primera consulta del artículo en O (número de departamentos) sin modificar las consultas y sin escribir triggers. En el esquema propuesto, en la etapa de desarrollo, no es necesario preocuparse por la estructura de almacenamiento de datos ni por qué agregaciones utilizar. Todo esto se puede cambiar en tiempo real durante la explotación.
En la práctica, esto se ve de la siguiente manera. Algunas personas desarrollan directamente la lógica basada en la tarea establecida. No se ocupan de los algoritmos y su complejidad, ni de los planes de ejecución, ni de los tipos de joins, ni de ningún otro componente técnico. Estas personas son más analistas de negocios que desarrolladores. Luego, todo esto pasa a pruebas o explotación. Se activa el registro de consultas largas. Cuando se detecta una consulta lenta, otras personas (más técnicas, en esencia DBA) toman la decisión de activar MATERIALIZED en alguna función intermedia. De este modo, se ralentiza un poco la escritura (pues se requiere la actualización de un campo adicional en la transacción). Sin embargo, se acelera significativamente no solo esta consulta, sino también todas las demás que utilizan esta función. Al mismo tiempo, la decisión sobre qué función materializar se toma de manera relativamente sencilla. Dos parámetros principales: el número de posibles valores de entrada (exactamente tantas entradas habrá en la tabla correspondiente) y con qué frecuencia se utiliza en otras funciones.
Análogos.
En las bases de datos comerciales modernas, existen mecanismos similares: MATERIALIZED VIEW con FAST REFRESH (Oracle) y INDEXED VIEW (Microsoft SQL Server). En PostgreSQL, el MATERIALIZED VIEW no puede actualizarse en transacciones, solo a petición (y además con restricciones bastante estrictas), así que no lo consideraremos. Pero tienen varios problemas que limitan considerablemente su uso.
En primer lugar, se puede activar la materialización solo si ya se ha creado una vista normal. De lo contrario, será necesario reescribir otras consultas que accedan a la nueva vista creada para utilizar esta materialización. O dejar todo como está, pero sería al menos ineficiente, dado que hay ciertos datos ya precalculados que muchas consultas no utilizan siempre y los recalculan.
En segundo lugar, tienen una enorme cantidad de restricciones:
Oracle
5.3.8.4 Restricciones generales sobre Fast Refresh
La consulta definitoria de la vista materializada está restringida de la siguiente manera:
- La vista materializada no debe contener referencias a expresiones no repetitivas como
SYSDATEyROWNUM.- La vista materializada no debe contener referencias a
RAWoLONGRAWtipos de datos.- No puede contener una
SELECCIONARsubconsulta de lista.- No puede contener funciones analíticas (por ejemplo,
RANK) en laSELECCIONARcláusula.- No puede hacer referencia a una tabla en la que se defina un
XMLIndexíndice.- No puede contener una
MODELOcláusula.- No puede contener una
cláusula HAVING con una subconsulta.No puede contener consultas anidadas que tengan- CUALQUIER
TODOS,, o[START WITH …] CONNECT BYNOTEXISTS.- No puede contener una
No puede contener múltiples tablas detalle en diferentes sitios.cláusula.- Sobre
las vistas materializadas no pueden tener tablas detalle remotas.COMMITLas vistas materializadas anidadas deben tener un join o agregación.- Las vistas de unión materializadas y las vistas de agregación materializadas con un
- GROUP
BYno pueden seleccionar de una tabla organizada por índice.5.3.8.5 Restricciones sobre Fast Refresh en Vistas Materializadas con Solo UnionesLas consultas definitorias para vistas materializadas con solo uniones y sin agregados tienen las siguientes restricciones sobre fast refresh:
Todas las restricciones de «
- Restricciones Generales sobre Fast Refresh«.
- cláusulas o agregados.
BYno pueden seleccionar de una tabla organizada por índice.Los rowids de todas las tablas en la- lista deben aparecer en la
FROMlista de la consulta.SELECCIONARLos registros de vista materializada deben existir con rowids para todas las tablas base en la- No se puede crear una vista materializada actualizable rápidamente a partir de múltiples tablas con uniones simples que incluyan una columna de tipo objeto en el
FROMLos registros de vista materializada deben existir con rowids para todas las tablas base en la- declaración.
SELECCIONARAdemás, el método de actualización que elijas no será óptimamente eficiente si:La consulta definitoria utiliza una unión externa que se comporta como una unión interna. Si la consulta definitoria contiene tal unión, considera reescribir la consulta definitoria para contener una unión interna.
- La
- lista de la vista materializada contiene expresiones sobre columnas de múltiples tablas.
SELECCIONAR5.3.8.6 Restricciones sobre Fast Refresh en Vistas Materializadas con AgregadosLas consultas definitorias para vistas materializadas con agregados o uniones tienen las siguientes restricciones sobre fast refresh:
Se admite el refresh rápido para ambas
- Restricciones Generales sobre Fast Refresh«.
vistas materializadas de DEMANDA, sin embargo, se aplican las siguientes restricciones:
las vistas materializadas no pueden tener tablas detalle remotas.COMMITylas vistas materializadas no pueden tener tablas detalle remotas.Todas las tablas en la vista materializada deben tener registros de vista materializada, y los registros de vista materializada deben:Contener todas las columnas de la tabla referenciada en la vista materializada.
- Especificar con
- ROWID
- INCLUYENDO
NUEVASyVALORESEspecificar laSECUENCIA.- cláusula si se espera que la tabla tenga una mezcla de inserciones/cargas directas, eliminaciones y actualizaciones.
SoloSUMA- DESVEST
VARIANZA,COUNT,AVG,MAX,son compatibles con fast refresh.,MINyCOUNT(*)debe ser especificado.COUNT(*)debe ser especificado.- Las funciones agregadas deben ocurrir solo como la parte más externa de la expresión. Es decir, agregados como
AVG(AVG(x))oAVG(x)+AVG(x)no están permitidos.- Para cada agregado como
AVG(expr), el correspondienteCOUNT(expr)debe estar presente. Oracle recomienda queSUM(expr)se especifique.- Si
VARIANCE(expr)oSTDDEV(expr) se especifica,COUNT(expr)ySUM(expr)debe especificarse. Oracle recomienda queSUM(expr *expr)se especifique.- lista de la vista materializada contiene expresiones sobre columnas de múltiples tablas.
SELECCIONARla columna en la consulta definitoria no puede ser una expresión compleja con columnas de múltiples tablas base. Una posible solución a esto es utilizar una vista materializada anidada.- lista de la vista materializada contiene expresiones sobre columnas de múltiples tablas.
SELECCIONARla lista debe contener todasBYno pueden seleccionar de una tabla organizada por índice.las columnas.- La vista materializada no está basada en una o más tablas remotas.
- Si usas un
tipo de dato CHAR en las columnas de filtro de un registro de vista materializada, los conjuntos de caracteres del sitio maestro y la vista materializada deben ser los mismos.Si la vista materializada tiene uno de los siguientes, entonces la actualización rápida es compatible solo con inserciones DML convencionales y cargas directas.- Vistas materializadas con
- agregados
MINoCOUNT(*)Vistas materializadas que tienen- pero no
SUM(expr)Vistas materializadas sinCOUNT(expr)- Tal vista materializada se llama una vista materializada solo para inserciones.
COUNT(*)Una vista materializada con
- es actualizable rápidamente después de eliminar o realizar declaraciones DML mixtas si no tiene un
COUNT(*)oMINLa actualización rápida de max/min después de eliminar o realizar DML mixtos no tiene el mismo comportamiento que el caso solo para inserciones. Se eliminan y recomputan los valores max/min para los grupos afectados. Debes ser consciente de su impacto en el rendimiento.WHEREcláusula.
Las vistas materializadas con vistas nombradas o subconsultas en la- la cláusula pueden actualizarse rápidamente siempre que las vistas puedan combinarse completamente. Para información sobre qué vistas se combinarán, consulta
FROMReferencia del Lenguaje SQL de Oracle Database .- Las vistas agregadas materializadas con uniones externas son actualizables rápidamente después de DML convencionales y cargas directas, siempre que solo se haya modificado la tabla externa. Además, deben existir restricciones únicas en las columnas de unión de la tabla de unión interna. Si hay uniones externas, todas las uniones deben estar conectadas por
WHEREcláusula.- y deben utilizar el operador de igualdad (
Y) operator.=Para las vistas materializadas con- CUBE
ROLLUP,, conjuntos de agrupamiento, o concatenación de ellos, se aplican las siguientes restricciones:la lista debe contener un diferenciador de agrupamiento que puede ser un
- lista de la vista materializada contiene expresiones sobre columnas de múltiples tablas.
SELECCIONARfunción GROUPING_ID en todaslas expresiones ofunciones GROUPING, una para cadaBYno pueden seleccionar de una tabla organizada por índice.expresión. Por ejemplo, si lala cláusula de la vista materializada es «CUBE(a, b)BYno pueden seleccionar de una tabla organizada por índice.«, entonces laBYno pueden seleccionar de una tabla organizada por índice.la lista debe contener ya «BYno pueden seleccionar de una tabla organizada por índice.GROUPING_ID(a, b)» o «SELECCIONARGROUPING(a)GROUPING(b)» para que la vista materializada sea actualizable rápidamente.no debe resultar en agrupaciones duplicadas. Por ejemplo, «YGROUP BY a, ROLLUP(a, b)» no es actualizable rápidamente porque resulta en agrupaciones duplicadas «BYno pueden seleccionar de una tabla organizada por índice.(a), (a, b), Y (a)5.3.8.7 Restricciones sobre la Actualización Rápida de las Vistas Materializadas con UNION ALLLas vistas materializadas con elUNION«.el operador de conjunto soporta la
REFRESH
RÁPIDO, osi se satisfacen las siguientes condiciones:La consulta definitoria debe tener eloperador en el nivel superior.El operador no puede estar incrustado dentro de una subconsulta, con una excepción: El
- puede estar en una subconsulta en la
RÁPIDO, ola cláusula siempre que la consulta definitoria tenga la formalista de la vista materializada contiene expresiones sobre columnas de múltiples tablas.
RÁPIDO, oSELECT * FROMRÁPIDO, o(vista o subconsulta conFROM) como en el siguiente ejemplo:CREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM customers c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM customers c WHERE c.cust_last_name = 'Jones');CREATE MATERIALIZED VIEW unionall_inside_view_mv REFRESH FAST ON DEMAND AS SELECT * FROM view_with_unionall;Ten en cuenta que la vistaRÁPIDO, oview_with_unionallcumple con los requisitos para actualización rápida.Cada bloque de consulta en la
la consulta debe cumplir con los requisitos de una vista materializada actualizable rápidamente con agregados o una vista materializada actualizable rápidamente con uniones.Los registros de vista materializada apropiados deben crearse en las tablas según lo requerido para el tipo correspondiente de vista materializada actualizable rápidamente.- Cada bloque de consulta en el
RÁPIDO, ola consulta debe cumplir con los requisitos de una vista materializada refrescable rápida con agregados o una vista materializada refrescable rápida con uniones.Los registros de vista materializada apropiados deben ser creados en las tablas según sea necesario para el tipo correspondiente de vista materializada refrescable rápida.
Tenga en cuenta que la base de datos de Oracle también permite el caso especial de una vista materializada de una sola tabla con uniones únicamente proporcionadas queNUEVASla columna se haya incluido en elSELECCIONARlistado y en el registro de la vista materializada. Esto se muestra en la consulta definitoria de la vistala consulta debe cumplir con los requisitos de una vista materializada actualizable rápidamente con agregados o una vista materializada actualizable rápidamente con uniones..- lista de la vista materializada contiene expresiones sobre columnas de múltiples tablas.
SELECCIONARla lista de cada consulta debe incluir unRÁPIDO, omarcador, y elRÁPIDO, ola columna debe tener un valor único constante numérico o de cadena en cadaRÁPIDO, orama. Además, la columna del marcador debe aparecer en la misma posición ordinal en elSELECCIONARlista de cada bloque de consulta. Consulte «» para más información sobreRÁPIDO, omarcadores.- Algunas características como las uniones externas, consultas de vista materializada solo de inserción y tablas remotas no son compatibles con vistas materializadas con
RÁPIDO, o. Tenga en cuenta, sin embargo, que las vistas materializadas utilizadas en la replicación, que no contienen uniones ni agregados, pueden actualizarse rápidamente cuandoRÁPIDO, oo se utilizan tablas remotas.- El parámetro de inicialización de compatibilidad debe establecerse en 9.2.0 o superior para crear una vista materializada que se pueda actualizar rápidamente con
RÁPIDO, o.
No quiero ofender a los aficionados de Oracle, pero a juzgar por su lista de restricciones, se da la impresión de que este mecanismo no fue desarrollado en términos generales, utilizando algún modelo, sino por miles de indios, a cada uno de los cuales se le permitió escribir su propia rama, y cada uno hizo lo que pudo. Utilizar este mecanismo para lógica real es como caminar por un campo minado. En cualquier momento se puede activar una mina al caer en una de las restricciones no evidentes. Cómo funciona esto es también una cuestión aparte, pero está fuera del alcance de este artículo.
Microsoft SQL Server
Requisitos Adicionales
Además de las opciones de SET y los requisitos de funciones determinísticas, se deben cumplir los siguientes requisitos:
- El usuario que ejecuta
CREAR ÍNDICEdebe ser el propietario de la vista.- Cuando crea el índice, la
IGNORE_DUP_KEYla opción debe estar establecida en OFF (la configuración predeterminada).- Las tablas deben ser referenciadas por nombres de dos partes, schema.tablename en la definición de la vista.
- Las funciones definidas por el usuario que se referencian en la vista deben ser creadas utilizando la
CON UN ESQUEMA DE VINCULACIÓNopción.- Cualquier función definida por el usuario que se refiera en la vista debe ser referenciada por nombres de dos partes, <schema>.<function>.
- La propiedad de acceso a datos de una función definida por el usuario debe ser
SIN SQL, y la propiedad de acceso externo debe serNO.- Las funciones del tiempo de ejecución del lenguaje común (CLR) pueden aparecer en la lista de selección de la vista, pero no pueden ser parte de la definición de la clave del índice agrupado. Las funciones CLR no pueden aparecer en la cláusula WHERE de la vista o en la cláusula ON de una operación JOIN en la vista.
- Las funciones CLR y los métodos de tipos definidos por el usuario CLR utilizados en la definición de la vista deben tener las propiedades establecidas como se muestra en la siguiente tabla.
Propiedad
NoteDETERMINISTA = VERDADERO
Debe declararse explícitamente como un atributo del método de Microsoft .NET Framework.PRECISO = VERDADERO
Debe declararse explícitamente como un atributo del método de .NET Framework.ACCESO A DATOS = SIN SQL
Determinado estableciendo el atributo DataAccess en DataAccessKind.None y el atributo SystemDataAccess en SystemDataAccessKind.None.ACCESO EXTERNO = NO
Esta propiedad por defecto es NO para las rutinas CLR.- La vista debe ser creada utilizando el
CON UN ESQUEMA DE VINCULACIÓNopción.- La vista debe referenciar únicamente tablas base que están en la misma base de datos que la vista. La vista no puede referenciar otras vistas.
- La instrucción SELECT en la definición de la vista no debe contener los siguientes elementos de Transact-SQL:
COUNT
Funciones de conjunto de filas (OPENDATASOURCE,OPENQUERY,OPENROWSET, YOPENXML)
EXTERNASuniones (IZQUIERDA,DERECHA[START WITH …] CONNECT BYCOMPLETA)Tabla derivada (definida especificando un
SELECCIONARinstrucción en laFROMcláusula)
Autouniones
Especificando columnas utilizandoSELECCIONAR *oSELECCIONAR .*
DISTINCT
DEVS,DEVP,VAR,VARP[START WITH …] CONNECT BYAVG
Expresión de tabla común (CTE)flotante1, text, ntext, image, XML[START WITH …] CONNECT BY filestream columnas
Subconsulta
SOBREcláusula, que incluye funciones de ventana de clasificación o agregaciónPredicados de texto completo (
CONTENIDO,FREETEXT)
VARIANZAfunción que hace referencia a una expresión anulable
ORDER BYFunción de agregado definida por el usuario CLR
MÁS ALTO
ROLLUP,, conjuntos de agrupamiento, o concatenación de ellos, se aplican las siguientes restricciones:[START WITH …] CONNECT BYCONJUNTOS DE AGRUPAMIENTOoperadores
MIN,COUNT(*)
RÁPIDO,EXCEPCIÓN[START WITH …] CONNECT BYINTERSECCIÓNoperadores
MUESTRA DE TABLAVariables de tabla
APLICACIÓN EXTERNAoCROSS APPLY
PIVOTE,DESPIVOTEConjuntos de columnas sparsas
Funciones de tabla valoradas en línea (TVF) o funciones de tabla valoradas de múltiples declaraciones (MSTVF)
OFFSET
CHECKSUM_AGG1 La vista indexada puede contener flotante columnas; sin embargo, tales columnas no pueden incluirse en la clave del índice agrupado.
- Si
GROUP BYestá presente, la definición de la VISTA debe contenerCONTAR_GRANDE(*)y no debe contenercláusula HAVING con una subconsulta.. EstasGROUP BYrestricciones son aplicables solo a la definición de vista indexada. Una consulta puede usar una vista indexada en su plan de ejecución incluso si no satisface estasGROUP BYrestricciones.- Si la definición de la vista contiene una
GROUP BYcláusula, la clave del índice único agrupado puede hacer referencia solo a las columnas especificadas en elGROUP BYcláusula.
Aquí se puede ver que los indios no fueron atraídos, ya que decidieron hacerlo bajo el esquema de "hacemos poco, pero bien". Es decir, tienen más minas en el campo, pero su ubicación es más transparente. Lo que más decepciona es esta restricción:
La vista debe referenciar únicamente tablas base que están en la misma base de datos que la vista. La vista no puede referenciar otras vistas.
En nuestra terminología, esto significa que una función no puede llamar a otra función materializada. Esto corta toda la ideología de raíz.
Además, esta restricción (y las siguientes en el texto) reduce drásticamente las opciones de uso:
La instrucción SELECT en la definición de la vista no debe contener los siguientes elementos de Transact-SQL:
COUNT
Funciones de conjunto de filas (OPENDATASOURCE,OPENQUERY,OPENROWSET, YOPENXML)
EXTERNASuniones (IZQUIERDA,DERECHA[START WITH …] CONNECT BYCOMPLETA)Tabla derivada (definida especificando un
SELECCIONARinstrucción en laFROMcláusula)
Autouniones
Especificando columnas utilizandoSELECCIONAR *oSELECCIONAR .*
DISTINCT
DEVS,DEVP,VAR,VARP[START WITH …] CONNECT BYAVG
Expresión de tabla común (CTE)flotante1, text, ntext, image, XML[START WITH …] CONNECT BY filestream columnas
Subconsulta
SOBREcláusula, que incluye funciones de ventana de clasificación o agregaciónPredicados de texto completo (
CONTENIDO,FREETEXT)
VARIANZAfunción que hace referencia a una expresión anulable
ORDER BYFunción de agregado definida por el usuario CLR
MÁS ALTO
ROLLUP,, conjuntos de agrupamiento, o concatenación de ellos, se aplican las siguientes restricciones:[START WITH …] CONNECT BYCONJUNTOS DE AGRUPAMIENTOoperadores
MIN,COUNT(*)
RÁPIDO,EXCEPCIÓN[START WITH …] CONNECT BYINTERSECCIÓNoperadores
MUESTRA DE TABLAVariables de tabla
APLICACIÓN EXTERNAoCROSS APPLY
PIVOTE,DESPIVOTEConjuntos de columnas sparsas
Funciones de tabla valoradas en línea (TVF) o funciones de tabla valoradas de múltiples declaraciones (MSTVF)
OFFSET
CHECKSUM_AGG
Se prohíben JOINs EXTERNOS, UNIÓN, ORDER BY y otros. Quizás hubiera sido más fácil indicar qué se puede usar en lugar de lo que no se puede. La lista probablemente sería mucho más corta.
En resumen: un enorme conjunto de restricciones en cada SGBD (comercial, lo señalaré) frente a ninguna (excepto una lógica, no técnica) en la tecnología LGPL. Sin embargo, cabe destacar que implementar este mecanismo en lógica relacional es algo más complicado que en la funcionalidad descrita.
Implementación
¿Cómo funciona? Se utiliza PostgreSQL como "máquina virtual". Dentro hay un algoritmo complejo que se encarga de construir consultas. Aquí . Y no es solo un gran conjunto de heurísticas con un montón de ifs. Así que, si hay un par de meses para estudiar, pueden intentar entender la arquitectura.
¿Funciona esto de manera efectiva? Suficientemente efectivo. Desafortunadamente, es difícil probarlo. Solo puedo decir que, si consideramos miles de consultas que existen en grandes aplicaciones, en promedio son más eficientes que las de un buen desarrollador. Un excelente programador de SQL puede escribir cualquier consulta de manera más eficiente, pero en mil consultas simplemente no tendrá ni la motivación ni el tiempo para hacerlo. Lo único que puedo presentar ahora como prueba de efectividad es que en la plataforma construida sobre esta base de datos funcionan varios proyectos. , que tienen miles de diversas funciones MATERIALIZED, con miles de usuarios y bases de terabytes con cientos de millones de registros, operando en un servidor de dos procesadores común. Sin embargo, cualquier persona interesada puede comprobar/desmentir la efectividad, descargando y PostgreSQL, el registro de consultas SQL y tratando de modificar allí la lógica y los datos.
En los próximos artículos, también hablaré sobre cómo se pueden establecer restricciones en funciones, trabajar con sesiones de cambios y mucho más.
Fuente: habr.com
