Equilibrar escrituras y lecturas en la base de datos

Equilibrar escrituras y lecturas en la base de datos
En el anterior статье Describí el concepto y la implementación de una base de datos construida sobre la base de funciones, en lugar de tablas y campos como en las bases de datos relacionales. Proporcionó muchos ejemplos que muestran las ventajas de este enfoque sobre el clásico. Muchos no los encontraron lo suficientemente convincentes.

En este artículo, mostraré cómo este concepto le permite equilibrar de manera rápida y conveniente las escrituras y lecturas en la base de datos sin ningún cambio en la lógica operativa. Se ha intentado implementar una funcionalidad similar en DBMS comerciales modernos (en particular, Oracle y Microsoft SQL Server). Al final del artículo mostraré que lo que hicieron, por decirlo suavemente, no salió muy bien.

Descripción

Como antes, para una mejor comprensión comenzaré la descripción con ejemplos. Digamos que necesitamos implementar una lógica que devolverá una lista de departamentos con la cantidad de empleados en ellos y su salario total.

En una base de datos funcional se vería así:

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 complejidad de ejecutar esta consulta en cualquier DBMS será equivalente a O(número de empleados)porque este cálculo requiere escanear toda la tabla de empleados y luego agruparlos por departamento. También habrá algún pequeño complemento (creemos que hay muchos más empleados que departamentos) dependiendo del plan elegido O(registro del número de empleados) o O(número de departamentos) para agrupar, etc.

Está claro que la sobrecarga de ejecución puede ser diferente en diferentes DBMS, pero la complejidad no cambiará de ninguna manera.

En la implementación propuesta, el DBMS funcional generará una subconsulta que calculará los valores requeridos para el departamento y luego realizará un JOIN con la tabla del departamento para obtener el nombre. Sin embargo, para cada función, al declarar, es posible establecer un marcador MATERIALIZADO especial. El sistema creará automáticamente un campo correspondiente para cada función. Al cambiar el valor de una función, el valor del campo también cambiará en la misma transacción. Al acceder a esta función se accederá al campo precalculado.

En particular, si configura MATERIALIZED para funciones contar empleados и salarioSuma, luego se agregarán dos campos a la tabla con la lista de departamentos, que almacenarán la cantidad de empleados y su salario total. Siempre que haya un cambio en los empleados, sus salarios o afiliaciones departamentales, el sistema cambiará automáticamente los valores de estos campos. La consulta anterior accederá a estos campos directamente y se ejecutará en O(número de departamentos).

¿Cuáles son las restricciones? Sólo una cosa: dicha función debe tener un número finito de valores de entrada para los cuales se define su valor. De lo contrario, será imposible 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’ (Department d, NUMERIC[10,2] N) = 
    GROUP SUM salary(Employee e) IF department(e) = d AND salary(e) > N;

Esta función está definida para un número infinito de valores de N (por ejemplo, cualquier valor negativo es adecuado). Por lo tanto, no puedes ponerle MATERIALIZADO. Así que esta es una limitación lógica, no técnica (es decir, no porque no podamos implementarla). De lo contrario, no hay restricciones. Puede utilizar agrupaciones, clasificación, Y y O, PARTICIÓN, recursividad, etc.

Por ejemplo, en el problema 2.2 del artículo anterior, puedes poner MATERIALIZED en ambas funciones:

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 propio sistema creará una tabla con claves de tipo. Local , Producto и INTEGER, le agregará dos campos y actualizará los valores de los campos con cualquier cambio. Cuando se realicen más llamadas a estas funciones, no se calcularán, sino que se leerán los valores de los campos correspondientes.

Con este mecanismo, puede, por ejemplo, deshacerse de las recursiones (CTE) en las consultas. En particular, considere grupos que forman un árbol usando la relación hijo/padre (cada grupo tiene un vínculo con su padre):

parent = DATA Group (Group);

En una base de datos funcional, la lógica de recursividad se puede especificar de la siguiente 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;

Ya que para la función es padre está marcado como MATERIALIZADO, luego se creará para él una tabla con dos claves (grupos), en la que el campo es padre será verdadero solo si la primera clave es hija de la segunda. El número de entradas en esta tabla será igual al número de grupos multiplicado por la profundidad promedio del árbol. Si necesitas, por ejemplo, contar el número de descendientes de un determinado grupo, puedes utilizar esta función:

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

No habrá CTE en la consulta SQL. En su lugar habrá un simple GRUPO POR.

Usando este mecanismo, también puedes desnormalizar fácilmente la base de datos si es necesario:

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

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

Al llamar a una función datos para la línea de pedido, el campo para el cual existe un índice se leerá de la tabla con líneas de pedido. Cuando cambia la fecha del pedido, el propio sistema volverá a calcular automáticamente la fecha desnormalizada en la línea.

Ventajas

¿Para qué sirve todo este mecanismo? En los DBMS clásicos, sin reescribir consultas, un desarrollador o DBA solo puede cambiar índices, determinar estadísticas e indicarle al planificador de consultas cómo ejecutarlas (y los HINT solo están disponibles en DBMS comerciales). No importa cuánto lo intenten, no podrán completar la primera consulta del artículo en O (número de departamentos) sin cambiar consultas ni agregar desencadenantes. En el esquema propuesto, en la etapa de desarrollo no es necesario pensar en la estructura de almacenamiento de datos ni en qué agregaciones utilizar. Todo esto se puede cambiar fácilmente sobre la marcha, directamente en funcionamiento.

En la práctica se ve así. Algunas personas desarrollan una lógica basada directamente en la tarea que tienen entre manos. No entienden de algoritmos y su complejidad, ni de planes de ejecución, ni de tipos de uniones, ni de ningún otro componente técnico. Estas personas son más analistas de negocios que desarrolladores. Luego, todo esto pasa a pruebas u operación. Permite el registro de consultas de larga duración. Cuando se detecta una consulta larga, otras personas (más técnicas, esencialmente DBA) deciden habilitar MATERIALIZED en alguna función intermedia. Esto ralentiza un poco el registro (ya que requiere actualizar un campo adicional en la transacción). Sin embargo, no sólo se agiliza notablemente esta consulta, sino también todas las demás que utilizan esta función. Al mismo tiempo, decidir qué función materializar es relativamente fácil. Dos parámetros principales: el número de valores de entrada posibles (es decir, cuántos registros habrá en la tabla correspondiente) y con qué frecuencia se usa en otras funciones.

Análogos

Los DBMS comerciales modernos tienen mecanismos similares: VISTA MATERIALIZADA con ACTUALIZACIÓN RÁPIDA (Oracle) y VISTA INDEXADA (Microsoft SQL Server). En PostgreSQL, la VISTA MATERIALIZADA no se puede actualizar en una transacción, sino solo a pedido (e incluso con restricciones muy estrictas), por lo que no lo consideramos. Pero tienen varios problemas que limitan significativamente su uso.

En primer lugar, sólo puede habilitar la materialización si ya ha creado una VISTA normal. De lo contrario, tendrá que reescribir las solicitudes restantes para acceder a la vista recién creada y utilizar esta materialización. O dejar todo como está, pero al menos será ineficaz si hay ciertos datos ya calculados previamente, pero muchas consultas no siempre los utilizan, sino que los recalculan.

En segundo lugar, tienen una gran cantidad de restricciones:

Oracle

5.3.8.4 Restricciones generales sobre actualización rápida

La consulta de definición de la vista materializada está restringida de la siguiente manera:

  • La vista materializada no debe contener referencias a expresiones no repetidas como SYSDATE y ROWNUM.
  • La vista materializada no debe contener referencias a RAW or LONG RAW tipos de datos
  • No puede contener un SELECT subconsulta de lista.
  • No puede contener funciones analíticas (por ejemplo, RANK) En la SELECT cláusula.
  • No puede hacer referencia a una tabla en la que XMLIndex El índice está definido.
  • No puede contener un MODEL cláusula.
  • No puede contener un HAVING cláusula con una subconsulta.
  • No puede contener consultas anidadas que tengan ANY, ALLo NOT EXISTS.
  • No puede contener un [START WITH …] CONNECT BY cláusula.
  • No puede contener varias tablas de detalles en diferentes sitios.
  • ON COMMIT las vistas materializadas no pueden tener tablas de detalles remotos.
  • Las vistas materializadas anidadas deben tener una unión o un agregado.
  • Vistas de unión materializadas y vistas agregadas materializadas con un GROUP BY La cláusula no puede seleccionar de una tabla organizada por índice.

5.3.8.5 Restricciones a la actualización rápida en vistas materializadas solo con uniones

La definición de consultas para vistas materializadas solo con uniones y sin agregados tiene las siguientes restricciones de actualización rápida:

  • Todas las restricciones de «Restricciones generales sobre actualización rápida«.
  • no pueden tener GROUP BY cláusulas o agregados.
  • Rowids de todas las tablas del FROM La lista debe aparecer en el SELECT lista de la consulta.
  • Los registros de vistas materializadas deben existir con ID de fila para todas las tablas base en el FROM lista de la consulta.
  • No puede crear una vista materializada de actualización rápida a partir de varias tablas con combinaciones simples que incluyan una columna de tipo de objeto en el SELECT .

Además, el método de actualización que elija no será óptimamente eficiente si:

  • La consulta de definición utiliza una combinación externa que se comporta como una combinación interna. Si la consulta de definición contiene dicha combinación, considere reescribir la consulta de definición para que contenga una combinación interna.
  • El SELECT La lista de la vista materializada contiene expresiones en columnas de varias tablas.

5.3.8.6 Restricciones a la actualización rápida en vistas materializadas con agregados

La definición de consultas para vistas materializadas con agregados o combinaciones tiene las siguientes restricciones de actualización rápida:

La actualización rápida es compatible con ambos ON COMMIT y ON DEMAND vistas materializadas, sin embargo, se aplican las siguientes restricciones:

  • Todas las tablas de la vista materializada deben tener registros de vista materializada, y los registros de vista materializada deben:
    • Contiene todas las columnas de la tabla a la que se hace referencia en la vista materializada.
    • Especificar con ROWID y INCLUDING NEW VALUES.
    • Especifica el SEQUENCE cláusula si se espera que la tabla tenga una combinación de inserciones/cargas directas, eliminaciones y actualizaciones.

  • Solo SUM, COUNT, AVG, STDDEV, VARIANCE, MIN y MAX son compatibles para una actualización rápida.
  • COUNT(*) debe especificarse.
  • Las funciones agregadas deben aparecer solo como la parte más externa de la expresión. Es decir, agregados como AVG(AVG(x)) or AVG(x)+ AVG(x) no están permitidos.
  • Para cada agregado como AVG(expr), el correspondiente COUNT(expr) debe estar presente. Oracle recomienda que SUM(expr) se especifico.
  • If VARIANCE(expr) or STDDEV(expr) está especificado, COUNT(expr) y SUM(expr) debe especificarse. Oracle recomienda que SUM(expr *expr) se especifico.
  • El SELECT La columna de la consulta de definición no puede ser una expresión compleja con columnas de varias tablas base. Una posible solución a esto es utilizar una vista materializada anidada.
  • El SELECT la lista debe contener todos GROUP BY columnas
  • La vista materializada no se basa en una o más tablas remotas.
  • Si utiliza un CHAR tipo de datos en las columnas de filtro de un registro de vista materializada, los juegos 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 solo se admite en inserciones DML convencionales y cargas directas.
    • Vistas materializadas con MIN or MAX agregados
    • Vistas materializadas que tienen SUM(expr) pero no COUNT(expr)
    • Vistas materializadas sin COUNT(*)

    Esta vista materializada se denomina vista materializada de solo inserción.

  • Una visión materializada con MAX or MIN se actualiza rápidamente después de eliminar o mezclar declaraciones DML si no tiene un WHERE cláusula.
    La actualización rápida máxima/mínima después de eliminar o DML mixto no tiene el mismo comportamiento que el caso de solo inserción. Elimina y vuelve a calcular los valores máximo/mínimo para los grupos afectados. Debe ser consciente de su impacto en el rendimiento.
  • Vistas materializadas con vistas con nombre o subconsultas en el FROM La cláusula se puede actualizar rápidamente siempre que las vistas se puedan fusionar por completo. Para obtener información sobre qué vistas se fusionarán, consulte Referencia del lenguaje SQL de la base de datos Oracle.
  • Si no hay uniones externas, es posible que tenga selecciones y uniones arbitrarias en el WHERE cláusula.
  • Las vistas agregadas materializadas con uniones externas se actualizan rápidamente después de DML convencional y cargas directas, siempre que solo se haya modificado la tabla externa. Además, deben existir restricciones únicas en las columnas de combinación de la tabla de combinación interna. Si hay uniones externas, todas las uniones deben estar conectadas por ANDs y debe usar la igualdad (=) operador.
  • Para vistas materializadas con CUBE, ROLLUP, agrupación de conjuntos o concatenación de ellos, se aplican las siguientes restricciones:
    • El SELECT La lista debe contener un distintivo de agrupación que pueda ser un GROUPING_ID funcionar en todos GROUP BY expresiones o GROUPING funciones una para cada GROUP BY expresión. Por ejemplo, si el GROUP BY La cláusula de la vista materializada es "GROUP BY CUBE(a, b)", entonces el SELECT la lista debe contener "GROUPING_ID(a, b)»O«GROUPING(a) AND GROUPING(b)» para que la vista materializada se pueda actualizar rápidamente.
    • GROUP BY no debería dar lugar a agrupaciones duplicadas. Por ejemplo, "GROUP BY a, ROLLUP(a, b)"no se actualiza rápidamente porque genera agrupaciones duplicadas"(a), (a, b), AND (a)«.

5.3.8.7 Restricciones de actualización rápida en vistas materializadas con UNION ALL

Vistas materializadas con el UNION ALL configurar el soporte del operador REFRESH FAST opción si se cumplen las siguientes condiciones:

  • La consulta de definición debe tener la UNION ALL operador en el nivel superior.

    El UNION ALL El operador no se puede incrustar dentro de una subconsulta, con una excepción: el UNION ALL puede estar en una subconsulta en el FROM cláusula siempre que la consulta definitoria tenga la forma SELECT * FROM (ver o subconsultar con UNION ALL) como en el siguiente ejemplo:

    CREAR VISTA view_with_unionall AS (SELECCIONE c.rowid crid, c.cust_id, 2 umarker DE los clientes c DONDE c.cust_last_name = 'Smith' UNION TODOS SELECCIONE c.rowid crid, c.cust_id, 3 umarker DE los clientes c DONDE c.cust_last_name = 'Jones'); CREAR VISTA MATERIALIZADA unionall_inside_view_mv ACTUALIZAR RÁPIDAMENTE A DEMANDA COMO SELECCIONAR * DESDE view_with_unionall;
    

    Tenga en cuenta que la vista view_with_unionall satisface los requisitos de actualización rápida.

  • Cada bloque de consulta en el UNION ALL La consulta debe satisfacer los requisitos de una vista materializada de actualización rápida con agregados o una vista materializada de actualización rápida con uniones.

    Se deben crear los registros de vista materializada adecuados en las tablas según sea necesario para el tipo correspondiente de vista materializada de actualización rápida.
    Tenga en cuenta que Oracle Database también permite el caso especial de una vista materializada de una sola tabla con uniones solo siempre que ROWID La columna ha sido incluida en el SELECT lista y en el registro de vista materializada. Esto se muestra en la consulta de definición de la vista. view_with_unionall.

  • El SELECT La lista de cada consulta debe incluir un UNION ALL marcador, y el UNION ALL La columna debe tener un valor numérico o de cadena constante distinto en cada UNION ALL rama. Además, la columna de marcador debe aparecer en la misma posición ordinal en el SELECT lista de cada bloque de consulta. Ver "UNION ALL Marcador y reescritura de consultas» para obtener más información sobre UNION ALL marcadores
  • Algunas funciones, como las uniones externas, las consultas de vistas materializadas agregadas de solo inserción y las tablas remotas, no son compatibles con las vistas materializadas con UNION ALL. Sin embargo, tenga en cuenta que las vistas materializadas utilizadas en la replicación, que no contienen uniones ni agregados, se pueden actualizar rápidamente cuando UNION ALL o 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 UNION ALL.

No quiero ofender a los fanáticos de Oracle, pero a juzgar por su lista de restricciones, parece que este mecanismo no fue escrito en el caso general, utilizando algún tipo de modelo, sino por miles de indios, donde todos tuvieron la oportunidad de escribieron su propia rama, y ​​cada uno hizo lo que pudo y lo hizo. Usar este mecanismo para la lógica real es como caminar por un campo minado. Puedes conseguir una mina en cualquier momento cumpliendo una de las restricciones no obvias. Cómo funciona también es una cuestión aparte, pero está fuera del alcance de este artículo.

Microsoft SQL Server

Requerimientos adicionales

Además de las opciones SET y los requisitos de función deterministas, se deben cumplir los siguientes requisitos:

  • El usuario que ejecuta CREATE INDEX debe ser el propietario de la vista.
  • Cuando crea el índice, el IGNORE_DUP_KEY La opción debe estar configurada en APAGADO (la configuración predeterminada).
  • Las tablas deben estar referenciadas por nombres de dos partes, Esquema.nombre de tabla en la definición de vista.
  • Las funciones definidas por el usuario a las que se hace referencia en la vista deben crearse utilizando el WITH SCHEMABINDING .
  • Cualquier función definida por el usuario a la que se haga referencia en la vista debe estar referenciada mediante nombres de dos partes, ..
  • La propiedad de acceso a datos de una función definida por el usuario debe ser NO SQL, y la propiedad de acceso externo debe ser NO.
  • Las funciones de Common Language Runtime (CLR) pueden aparecer en la lista de selección de la vista, pero no pueden formar parte de la definición de la clave de í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 vista deben tener las propiedades establecidas como se muestra en la siguiente tabla.

    Propiedades
    Note

    DETERMINISTA = VERDADERO
    Debe declararse explícitamente como un atributo del método Microsoft .NET Framework.

    PRECISO = VERDADERO
    Debe declararse explícitamente como un atributo del método .NET Framework.

    ACCESO A DATOS = SIN SQL
    Se determina estableciendo el atributo DataAccess en DataAccessKind.None y el atributo SystemDataAccess en SystemDataAccessKind.None.

    ACCESO EXTERNO = NO
    Esta propiedad tiene el valor predeterminado NO para las rutinas CLR.

  • La vista debe crearse utilizando el WITH SCHEMABINDING .
  • La vista debe hacer referencia únicamente a tablas base que estén en la misma base de datos que la vista. La vista no puede hacer referencia a otras vistas.
  • La instrucción SELECT en la definición de vista no debe contener los siguientes elementos Transact-SQL:

    COUNT
    Funciones FILAS (OPENDATASOURCE, OPENQUERY, OPENROWSET, Y OPENXML)
    OUTER Uniones (LEFT, RIGHTo FULL)

    Tabla derivada (definida especificando un SELECT declaración en el FROM cláusula)
    Autouniones
    Especificación de columnas mediante el uso SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARPo AVG
    Expresión de tabla común (CTE)

    flotar1, texto, ntext, imagen, XMLo flujo de archivos columnas
    subconsulta
    OVER cláusula, que incluye funciones de clasificación o ventana agregada

    Predicados de texto completo (CONTAINS, FREETEXT)
    SUM función que hace referencia a una expresión que acepta valores NULL
    ORDER BY

    Función agregada CLR definida por el usuario
    TOP
    CUBE, ROLLUPo GROUPING SETS operadores

    MIN, MAX
    UNION, EXCEPTo INTERSECT operadores
    TABLESAMPLE

    Variables de tabla
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Conjuntos de columnas dispersas
    Funciones en línea (TVF) o con valores de tabla de declaraciones múltiples (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 La vista indexada puede contener flotar columnas; sin embargo, dichas columnas no se pueden incluir en la clave de índice agrupado.

  • If GROUP BY está presente, la definición VIEW debe contener COUNT_BIG(*) y no debe contener HAVING. Estas GROUP BY Las restricciones son aplicables sólo a la definición de vista indexada. Una consulta puede utilizar una vista indexada en su plan de ejecución incluso si no cumple con estos GROUP BY restricciones
  • Si la definición de vista contiene un GROUP BY cláusula, la clave del índice agrupado único puede hacer referencia solo a las columnas especificadas en el GROUP BY cláusula.

Aquí queda claro que los indios no estuvieron involucrados, ya que decidieron hacerlo según el esquema “haremos poco, pero bien”. Es decir, tienen más minas en el campo, pero su ubicación es más transparente. Lo más decepcionante es esta limitación:

La vista debe hacer referencia únicamente a tablas base que estén en la misma base de datos que la vista. La vista no puede hacer referencia a otras vistas.

En nuestra terminología, esto significa que una función no puede acceder a otra función materializada. Esto corta de raíz toda ideología.
Además, esta limitación (y más adelante en el texto) reduce en gran medida los casos de uso:

La instrucción SELECT en la definición de vista no debe contener los siguientes elementos Transact-SQL:

COUNT
Funciones FILAS (OPENDATASOURCE, OPENQUERY, OPENROWSET, Y OPENXML)
OUTER Uniones (LEFT, RIGHTo FULL)

Tabla derivada (definida especificando un SELECT declaración en el FROM cláusula)
Autouniones
Especificación de columnas mediante el uso SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARPo AVG
Expresión de tabla común (CTE)

flotar1, texto, ntext, imagen, XMLo flujo de archivos columnas
subconsulta
OVER cláusula, que incluye funciones de clasificación o ventana agregada

Predicados de texto completo (CONTAINS, FREETEXT)
SUM función que hace referencia a una expresión que acepta valores NULL
ORDER BY

Función agregada CLR definida por el usuario
TOP
CUBE, ROLLUPo GROUPING SETS operadores

MIN, MAX
UNION, EXCEPTo INTERSECT operadores
TABLESAMPLE

Variables de tabla
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Conjuntos de columnas dispersas
Funciones en línea (TVF) o con valores de tabla de declaraciones múltiples (MSTVF)
OFFSET

CHECKSUM_AGG

Se prohíben JUNTAS EXTERIORES, UNIÓN, ORDEN POR y otros. Podría haber sido más fácil especificar qué se podría utilizar en lugar de qué no. Probablemente la lista sería mucho más corta.

En resumen: un enorme conjunto de restricciones en todos los DBMS (tengamos en cuenta los comerciales) frente a ninguno (con la excepción de uno lógico, no técnico) en la tecnología LGPL. Sin embargo, cabe señalar que implementar este mecanismo en la lógica relacional es algo más difícil que en la lógica funcional descrita.

implementación

¿Cómo funciona? PostgreSQL se utiliza como una "máquina virtual". Hay un algoritmo complejo en su interior que genera consultas. Aquí codigo fuente. Y no hay sólo un gran conjunto de heurísticas con un montón de condiciones. Entonces, si tienes un par de meses para estudiar, puedes intentar entender la arquitectura.

¿Funciona eficazmente? Bastante efectivo. Desafortunadamente, esto es difícil de probar. Solo puedo decir que si consideramos las miles de consultas que existen en aplicaciones grandes, 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 con mil consultas simplemente no tendrá la motivación ni el tiempo para hacerlo. Lo único que puedo citar ahora como prueba de eficacia es que varios proyectos están funcionando en la plataforma construida sobre este DBMS. sistemas ERP, que tienen miles de funciones MATERIALIZADAS diferentes, con miles de usuarios y bases de datos de terabytes con cientos de millones de registros ejecutándose en un servidor normal de dos procesadores. Sin embargo, cualquiera puede comprobar/refutar la eficacia descargando una plataforma y PostgreSQL, encendiendo registrar consultas SQL e intentar cambiar la lógica y los datos allí.

En los siguientes artículos, también hablaré sobre cómo establecer restricciones de funciones, trabajar con sesiones de cambio y mucho más.

Fuente: habr.com

Añadir un comentario