Balanceamento de gravações e leituras em um banco de dados

Balanceamento de gravações e leituras em um banco de dados
No anterior статье Descrevi o conceito e a implementação de um banco de dados construído com base em funções, em vez de tabelas e campos como nos bancos de dados relacionais. Forneceu muitos exemplos que mostram as vantagens desta abordagem sobre a clássica. Muitos acharam que não eram convincentes o suficiente.

Neste artigo, mostrarei como esse conceito permite equilibrar gravações e leituras no banco de dados de maneira rápida e conveniente, sem qualquer alteração na lógica operacional. Foi tentada implementar funcionalidade semelhante em SGBDs comerciais modernos (em particular, Oracle e Microsoft SQL Server). No final do artigo mostrarei que o que eles fizeram, para dizer o mínimo, não deu muito certo.

descrição

Como antes, para melhor compreensão iniciarei a descrição com exemplos. Digamos que precisamos implementar uma lógica que retornará uma lista de departamentos com o número de funcionários neles e seu salário total.

Em um banco de dados funcional ficaria assim:

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

A complexidade de executar esta consulta em qualquer SGBD será equivalente a O(número de funcionários)pois esse cálculo exige a varredura de toda a tabela de funcionários e depois agrupá-los por departamento. Haverá também alguns pequenos complementos (acreditamos que haja muito mais funcionários do que departamentos) dependendo do plano escolhido O (registro do número de funcionários) ou O(número de departamentos) para agrupamento e assim por diante.

É claro que a sobrecarga de execução pode ser diferente em diferentes SGBDs, mas a complexidade não mudará de forma alguma.

Na implementação proposta, o SGBD funcional irá gerar uma subconsulta que calculará os valores necessários para o departamento, e então fará um JOIN com a tabela do departamento para obter o nome. Porém, para cada função, ao declarar, é possível definir um marcador MATERIALIZED especial. O sistema criará automaticamente um campo correspondente para cada função. Ao alterar o valor de uma função, o valor do campo também será alterado na mesma transação. Ao acessar esta função será acessado o campo pré-calculado.

Em particular, se você definir MATERIALIZED para funções contarFuncionários и salárioSoma, então serão adicionados dois campos à tabela com a lista de departamentos, que armazenará o número de funcionários e seu salário total. Sempre que houver alteração de funcionários, salários ou filiações departamentais, o sistema alterará automaticamente os valores desses campos. A consulta acima acessará esses campos diretamente e será executada em O(número de departamentos).

Quais são as restrições? Apenas uma coisa: tal função deve ter um número finito de valores de entrada para os quais seu valor é definido. Caso contrário, será impossível construir uma tabela que armazene todos os seus valores, pois não pode haver uma tabela com um número infinito de linhas.

Exemplo:

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

Esta função é definida para um número infinito de valores de N (por exemplo, qualquer valor negativo é adequado). Portanto, você não pode colocar MATERIALIZED nele. Portanto, esta é uma limitação lógica, não técnica (ou seja, não porque não pudéssemos implementá-la). Caso contrário, não há restrições. Você pode usar agrupamentos, classificação, AND e OR, PARTIÇÃO, recursão, etc.

Por exemplo, no problema 2.2 do artigo anterior, você pode colocar MATERIALIZED em ambas as funções:

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;

O próprio sistema criará uma tabela com chaves de tipo Experiência e dinâmica de loja, Produto и INTEGER, adicionará dois campos a ele e atualizará os valores dos campos neles com quaisquer alterações. Quando forem feitas novas chamadas para essas funções, elas não serão calculadas, mas sim os valores serão lidos nos campos correspondentes.

Usando esse mecanismo, você pode, por exemplo, se livrar de recursões (CTE) em consultas. Em particular, considere grupos que formam uma árvore usando o relacionamento filho/pai (cada grupo tem um link para seu pai):

parent = DATA Group (Group);

Em um banco de dados funcional, a lógica de recursão pode ser especificada da seguinte forma:

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;

Já que para a função éParente está marcado como MATERIALIZED, então será criada para ele uma tabela com duas chaves (grupos), na qual o campo éParente será verdadeiro somente se a primeira chave for filha da segunda. O número de entradas nesta tabela será igual ao número de grupos multiplicado pela profundidade média da árvore. Se precisar, por exemplo, contar o número de descendentes de um determinado grupo, você pode usar esta função:

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

Não haverá CTE na consulta SQL. Em vez disso, haverá um simples GROUP BY.

Usando este mecanismo, você também pode desnormalizar facilmente o banco de dados, se necessário:

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

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

Ao chamar uma função dados para a linha do pedido, o campo para o qual existe um índice será lido da tabela com as linhas do pedido. Quando a data do pedido for alterada, o próprio sistema recalculará automaticamente a data desnormalizada na linha.

Vantagens

Para que serve todo esse mecanismo? Em SGBDs clássicos, sem reescrever consultas, um desenvolvedor ou DBA pode apenas alterar índices, determinar estatísticas e informar ao planejador de consultas como executá-las (e HINTs estão disponíveis apenas em SGBDs comerciais). Não importa o quanto tentem, eles não conseguirão concluir a primeira consulta do artigo em O (número de departamentos) sem alterar consultas ou adicionar gatilhos. No esquema proposto, na fase de desenvolvimento você não precisa pensar na estrutura de armazenamento de dados e em quais agregações usar. Tudo isso pode ser facilmente alterado em tempo real, diretamente na operação.

Na prática é assim. Algumas pessoas desenvolvem lógica diretamente com base na tarefa em questão. Não entendem algoritmos e sua complexidade, nem planos de execução, nem tipos de junções, nem qualquer outro componente técnico. Essas pessoas são mais analistas de negócios do que desenvolvedores. Então, tudo isso vai para teste ou operação. Permite o registro de consultas de longa duração. Quando uma consulta longa é detectada, outras pessoas (mais técnicas - essencialmente DBA) decidem habilitar MATERIALIZED em alguma função intermediária. Isso retarda um pouco a gravação (pois exige a atualização de um campo adicional na transação). Porém, não só esta consulta é significativamente acelerada, mas também todas as outras que utilizam esta função. Ao mesmo tempo, decidir qual função materializar é relativamente simples. Dois parâmetros principais: o número de valores de entrada possíveis (é quantos registros estarão na tabela correspondente) e com que frequência ele é usado em outras funções.

Análises

Os SGBDs comerciais modernos possuem mecanismos semelhantes: MATERIALIZED VIEW com FAST REFRESH (Oracle) e INDEXED VIEW (Microsoft SQL Server). No PostgreSQL, MATERIALIZED VIEW não pode ser atualizado em uma transação, mas apenas mediante solicitação (e mesmo com restrições muito rígidas), por isso não o consideramos. Mas eles têm vários problemas que limitam significativamente o seu uso.

Primeiramente, você só pode habilitar a materialização se já tiver criado uma VIEW regular. Caso contrário, você terá que reescrever as solicitações restantes para acessar a visão recém-criada para usar esta materialização. Ou deixe tudo como está, mas será no mínimo ineficaz se houver alguns dados já pré-calculados, mas muitas consultas nem sempre os utilizam, mas os recalculam.

Em segundo lugar, eles têm um grande número de restrições:

Oracle

5.3.8.4 Restrições Gerais à Atualização Rápida

A consulta que define a visão materializada é restrita da seguinte forma:

  • A visão materializada não deve conter referências a expressões não repetitivas como SYSDATE e ROWNUM.
  • A visão materializada não deve conter referências a RAW or LONG RAW tipos de dados.
  • Não pode conter um SELECT subconsulta de lista.
  • Não pode conter funções analíticas (por exemplo, RANK) Na SELECT cláusula.
  • Ele não pode fazer referência a uma tabela na qual um XMLIndex índice é definido.
  • Não pode conter um MODEL cláusula.
  • Não pode conter um HAVING cláusula com uma subconsulta.
  • Ele não pode conter consultas aninhadas que tenham ANY, ALLou NOT EXISTS.
  • Não pode conter um [START WITH …] CONNECT BY cláusula.
  • Ele não pode conter diversas tabelas de detalhes em locais diferentes.
  • ON COMMIT visualizações materializadas não podem ter tabelas de detalhes remotas.
  • As visualizações materializadas aninhadas devem ter uma junção ou agregação.
  • Visualizações de junção materializadas e visualizações agregadas materializadas com um GROUP BY A cláusula não pode selecionar em uma tabela organizada por índice.

5.3.8.5 Restrições à atualização rápida em visualizações materializadas somente com junções

A definição de consultas para visualizações materializadas apenas com junções e sem agregações tem as seguintes restrições na atualização rápida:

  • Todas as restrições de «Restrições gerais à atualização rápida".
  • Eles não podem ter GROUP BY cláusulas ou agregados.
  • Rowids de todas as tabelas do FROM lista deve aparecer no SELECT lista da consulta.
  • Os logs de visualização materializados devem existir com rowids para todas as tabelas base no FROM lista da consulta.
  • Você não pode criar uma visualização materializada de atualização rápida a partir de diversas tabelas com junções simples que incluam uma coluna de tipo de objeto no arquivo SELECT declaração.

Além disso, o método de atualização escolhido não será eficiente se:

  • A consulta de definição usa uma junção externa que se comporta como uma junção interna. Se a consulta de definição contiver tal junção, considere reescrever a consulta de definição para conter uma junção interna.
  • A SELECT A lista da visualização materializada contém expressões em colunas de diversas tabelas.

5.3.8.6 Restrições à atualização rápida em visualizações materializadas com agregações

A definição de consultas para visualizações materializadas com agregações ou junções tem as seguintes restrições na atualização rápida:

A atualização rápida é suportada para ambos ON COMMIT e ON DEMAND visualizações materializadas, no entanto, as seguintes restrições se aplicam:

  • Todas as tabelas na visualização materializada devem ter logs de visualização materializada, e os logs de visualização materializada devem:
    • Contém todas as colunas da tabela referenciada na visualização materializada.
    • Especificar com ROWID e INCLUDING NEW VALUES.
    • Especifique o SEQUENCE cláusula se for esperado que a tabela tenha uma combinação de inserções/carregamentos diretos, exclusões e atualizações.

  • Somente SUM, COUNT, AVG, STDDEV, VARIANCE, MIN e MAX são suportados para atualização rápida.
  • COUNT(*) deve ser especificado.
  • As funções agregadas devem ocorrer apenas como a parte mais externa da expressão. Ou seja, agregados como AVG(AVG(x)) or AVG(x)+ AVG(x) não é permitido.
  • Para cada agregado como AVG(expr), o correspondente COUNT(expr) deve estar presente. A Oracle recomenda que SUM(expr) ser especificado.
  • If VARIANCE(expr) or STDDEV(expr) é especificado, COUNT(expr) e SUM(expr) deve ser especificado. A Oracle recomenda que SUM(expr *expr) ser especificado.
  • A SELECT coluna na consulta de definição não pode ser uma expressão complexa com colunas de diversas tabelas base. Uma possível solução para isso é usar uma visualização materializada aninhada.
  • A SELECT a lista deve conter todos GROUP BY colunas.
  • A visão materializada não se baseia em uma ou mais tabelas remotas.
  • Se você usar um CHAR tipo de dados nas colunas de filtro de um log de visualização materializada, os conjuntos de caracteres do site mestre e da visualização materializada deverão ser iguais.
  • Se a visualização materializada tiver um dos seguintes itens, a atualização rápida terá suporte apenas em inserções DML convencionais e carregamentos diretos.
    • Visualizações materializadas com MIN or MAX agregados para construção
    • Visualizações materializadas que têm SUM(expr) mas não COUNT(expr)
    • Visualizações materializadas sem COUNT(*)

    Essa visão materializada é chamada de visão materializada somente de inserção.

  • Uma visão materializada com MAX or MIN é rapidamente atualizável após exclusão ou instruções DML mistas se não tiver um WHERE cláusula.
    A atualização rápida máxima/mínima após exclusão ou DML misto não tem o mesmo comportamento que o caso somente inserção. Ele exclui e recalcula os valores máximo/mínimo para os grupos afetados. Você precisa estar ciente de seu impacto no desempenho.
  • Visualizações materializadas com visualizações nomeadas ou subconsultas no FROM cláusula pode ser atualizada rapidamente, desde que as visualizações possam ser completamente mescladas. Para obter informações sobre quais visualizações serão mescladas, consulte Referência da Linguagem SQL do Banco de Dados Oracle.
  • Se não houver junções externas, você poderá ter seleções e junções arbitrárias no WHERE cláusula.
  • As visualizações agregadas materializadas com junções externas são rapidamente atualizáveis ​​após DML convencional e cargas diretas, desde que apenas a tabela externa tenha sido modificada. Além disso, devem existir restrições exclusivas nas colunas de junção da tabela de junção interna. Se houver junções externas, todas as junções deverão ser conectadas por ANDs e deve usar a igualdade (=) operador.
  • Para visualizações materializadas com CUBE, ROLLUP, agrupamento de conjuntos ou concatenação deles, aplicam-se as seguintes restrições:
    • A SELECT lista deve conter um diferenciador de agrupamento que pode ser um GROUPING_ID funcionar em todos GROUP BY expressões ou GROUPING funções uma para cada GROUP BY expressão. Por exemplo, se o GROUP BY cláusula da visão materializada é "GROUP BY CUBE(a, b)", então o SELECT lista deve conter "GROUPING_ID(a, b)»Ou«GROUPING(a) AND GROUPING(b)» para que a visão materializada seja atualizada rapidamente.
    • GROUP BY não deve resultar em agrupamentos duplicados. Por exemplo, "GROUP BY a, ROLLUP(a, b)"não é atualizável rapidamente porque resulta em agrupamentos duplicados"(a), (a, b), AND (a)".

5.3.8.7 Restrições à atualização rápida em visualizações materializadas com UNION ALL

Visualizações materializadas com o UNION ALL definir o suporte do operador REFRESH FAST opção se as seguintes condições forem satisfeitas:

  • A consulta definidora deve ter o UNION ALL operador no nível superior.

    A UNION ALL O operador não pode ser incorporado em uma subconsulta, com uma exceção: o UNION ALL pode estar em uma subconsulta no FROM cláusula desde que a consulta definidora esteja no formato SELECT * FROM (visualização ou subconsulta com UNION ALL) como no exemplo a seguir:

    CREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umrker FROM clientes c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umrker FROM clientes c WHERE c.cust_last_name = 'Jones'); CRIAR VISUALIZAÇÃO MATERIALIZADA unionall_inside_view_mv ATUALIZAR RÁPIDO SOB DEMANDA COMO SELECT * FROM view_with_unionall;
    

    Observe que a visão view_with_unionall satisfaz os requisitos para atualização rápida.

  • Cada bloco de consulta no UNION ALL A consulta deve satisfazer os requisitos de uma visão materializada de atualização rápida com agregações ou de uma visão materializada de atualização rápida com junções.

    Os logs de visualização materializada apropriados devem ser criados nas tabelas conforme necessário para o tipo correspondente de visualização materializada de atualização rápida.
    Observe que o banco de dados Oracle também permite o caso especial de uma visualização materializada de tabela única com junções apenas desde que o ROWID coluna foi incluída na SELECT lista e no log de visualização materializada. Isso é mostrado na consulta de definição da visualização view_with_unionall.

  • A SELECT lista de cada consulta deve incluir um UNION ALL marcador, e o UNION ALL coluna deve ter um valor numérico ou de string constante distinto em cada UNION ALL filial. Além disso, a coluna do marcador deve aparecer na mesma posição ordinal no SELECT lista de cada bloco de consulta. Ver "Marcador UNION ALL e reescrita de consulta» para mais informações sobre UNION ALL marcadores.
  • Alguns recursos, como junções externas, consultas de visualização materializada agregadas somente de inserção e tabelas remotas, não são suportados para visualizações materializadas com UNION ALL. Observe, entretanto, que as visualizações materializadas usadas na replicação, que não contêm junções ou agregações, podem ser atualizadas rapidamente quando UNION ALL ou tabelas remotas são usadas.
  • O parâmetro de inicialização de compatibilidade deve ser definido como 9.2.0 ou superior para criar uma visualização materializada de atualização rápida com UNION ALL.

Não quero ofender os fãs da Oracle, mas a julgar pela lista de restrições, parece que esse mecanismo foi escrito não no caso geral, usando algum tipo de modelo, mas por milhares de indianos, onde todos tiveram a oportunidade de escreveram seu próprio ramo, e cada um deles fez o que pôde. Usar esse mecanismo para lógica real é como caminhar por um campo minado. Você pode obter uma mina a qualquer momento, atingindo uma das restrições não óbvias. Como funciona também é uma questão separada, mas está além do escopo deste artigo.

Microsoft SQL Server

Requisitos adicionais

Além das opções SET e dos requisitos da função determinística, os seguintes requisitos devem ser atendidos:

  • O usuário que executa CREATE INDEX deve ser o proprietário da visualização.
  • Ao criar o índice, o IGNORE_DUP_KEY a opção deve ser definida como OFF (a configuração padrão).
  • As tabelas devem ser referenciadas por nomes de duas partes, esquema.tablename na definição da visualização.
  • As funções definidas pelo usuário referenciadas na visualização devem ser criadas usando o método WITH SCHEMABINDING opção.
  • Quaisquer funções definidas pelo usuário referenciadas na visualização devem ser referenciadas por nomes de duas partes, ..
  • A propriedade de acesso a dados de uma função definida pelo usuário deve ser NO SQL, e a propriedade de acesso externo deve ser NO.
  • As funções CLR (Common Language Runtime) podem aparecer na lista de seleção da visualização, mas não podem fazer parte da definição da chave de índice clusterizado. As funções CLR não podem aparecer na cláusula WHERE da visualização ou na cláusula ON de uma operação JOIN na visualização.
  • As funções CLR e os métodos de tipos CLR definidos pelo usuário usados ​​na definição da visualização devem ter as propriedades definidas conforme mostrado na tabela a seguir.

    Propriedade
    Note

    DETERMINISTA = VERDADEIRO
    Deve ser declarado explicitamente como um atributo do método Microsoft .NET Framework.

    PRECISO = VERDADEIRO
    Deve ser declarado explicitamente como um atributo do método .NET Framework.

    ACESSO A DADOS = SEM SQL
    Determinado pela configuração do atributo DataAccess como DataAccessKind.None e do atributo SystemDataAccess como SystemDataAccessKind.None.

    ACESSO EXTERNO = NÃO
    O padrão desta propriedade é NO para rotinas CLR.

  • A visualização deve ser criada usando o WITH SCHEMABINDING opção.
  • A visualização deve fazer referência apenas às tabelas base que estão no mesmo banco de dados que a visualização. A visualização não pode fazer referência a outras visualizações.
  • A instrução SELECT na definição da visualização não deve conter os seguintes elementos Transact-SQL:

    COUNT
    Funções ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, E OPENXML)
    OUTER junta-se (LEFT, RIGHTou FULL)

    Tabela derivada (definida pela especificação de um SELECT declaração no FROM cláusula)
    Auto-junções
    Especificando colunas usando SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARPou AVG
    Expressão de tabela comum (CTE)

    flutuar1, texto, ntext, imagem, XMLou fluxo de arquivos colunas
    subquery
    OVER cláusula, que inclui funções de classificação ou janela agregada

    Predicados de texto completo (CONTAINS, FREETEXT)
    SUM função que faz referência a uma expressão anulável
    ORDER BY

    Função agregada definida pelo usuário CLR
    TOP
    CUBE, ROLLUPou GROUPING SETS operadores

    MIN, MAX
    UNION, EXCEPTou INTERSECT operadores
    TABLESAMPLE

    Variáveis ​​de tabela
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Conjuntos de colunas esparsas
    Funções com valor de tabela embutidas (TVF) ou com múltiplas instruções (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 A visualização indexada pode conter flutuar colunas; entretanto, essas colunas não podem ser incluídas na chave de índice clusterizado.

  • If GROUP BY estiver presente, a definição VIEW deve conter COUNT_BIG(*) e não deve conter HAVING. Estes GROUP BY restrições são aplicáveis ​​somente à definição de visualização indexada. Uma consulta pode usar uma visão indexada em seu plano de execução mesmo que não satisfaça estes requisitos. GROUP BY restrições.
  • Se a definição da visualização contiver um GROUP BY cláusula, a chave do índice clusterizado exclusivo pode fazer referência apenas às colunas especificadas na GROUP BY cláusula.

Fica claro aqui que os índios não se envolveram, pois decidiram fazer segundo o esquema “faremos pouco, mas bem”. Ou seja, eles têm mais minas em campo, mas sua localização é mais transparente. O mais decepcionante é esta limitação:

A visualização deve fazer referência apenas às tabelas base que estão no mesmo banco de dados que a visualização. A visualização não pode fazer referência a outras visualizações.

Na nossa terminologia, isso significa que uma função não pode acessar outra função materializada. Isto corta toda a ideologia pela raiz.
Além disso, esta limitação (e mais adiante no texto) reduz bastante os casos de uso:

A instrução SELECT na definição da visualização não deve conter os seguintes elementos Transact-SQL:

COUNT
Funções ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, E OPENXML)
OUTER junta-se (LEFT, RIGHTou FULL)

Tabela derivada (definida pela especificação de um SELECT declaração no FROM cláusula)
Auto-junções
Especificando colunas usando SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARPou AVG
Expressão de tabela comum (CTE)

flutuar1, texto, ntext, imagem, XMLou fluxo de arquivos colunas
subquery
OVER cláusula, que inclui funções de classificação ou janela agregada

Predicados de texto completo (CONTAINS, FREETEXT)
SUM função que faz referência a uma expressão anulável
ORDER BY

Função agregada definida pelo usuário CLR
TOP
CUBE, ROLLUPou GROUPING SETS operadores

MIN, MAX
UNION, EXCEPTou INTERSECT operadores
TABLESAMPLE

Variáveis ​​de tabela
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Conjuntos de colunas esparsas
Funções com valor de tabela embutidas (TVF) ou com múltiplas instruções (MSTVF)
OFFSET

CHECKSUM_AGG

OUTER JOINS, UNION, ORDER BY e outros são proibidos. Poderia ter sido mais fácil especificar o que poderia ser usado em vez do que não poderia ser usado. A lista provavelmente seria muito menor.

Para resumir: um enorme conjunto de restrições em todos os SGBDs (vamos observar os comerciais) versus nenhum (com exceção de um lógico, não técnico) na tecnologia LGPL. No entanto, deve-se notar que a implementação deste mecanismo na lógica relacional é um pouco mais difícil do que na lógica funcional descrita.

Implementação

Como funciona? PostgreSQL é usado como uma “máquina virtual”. Existe um algoritmo complexo que cria consultas. Aqui código fonte. E não existe apenas um grande conjunto de heurísticas com vários ifs. Então, se você tem alguns meses para estudar, pode tentar entender arquitetura.

Funciona de forma eficaz? Bastante eficaz. Infelizmente, isso é difícil de provar. Só posso dizer que se considerarmos as milhares de consultas que existem em grandes aplicações, então em média elas são mais eficientes que as de um bom desenvolvedor. Um excelente programador SQL pode escrever qualquer consulta com mais eficiência, mas com mil consultas ele simplesmente não terá motivação ou tempo para fazê-lo. A única coisa que posso citar agora como prova de eficácia é que vários projetos estão funcionando na plataforma construída neste SGBD Sistemas ERP, que possuem milhares de funções MATERIALIZADAS diferentes, com milhares de usuários e bancos de dados de terabytes com centenas de milhões de registros em execução em um servidor regular de dois processadores. No entanto, qualquer pessoa pode verificar/refutar a eficácia baixando uma plataforma e PostgreSQL, ligadas registrando consultas SQL e tentando alterar a lógica e os dados.

Nos artigos a seguir também falarei sobre como você pode definir restrições de funções, trabalhar com sessões de alteração e muito mais.

Fonte: habr.com

Adicionar um comentário