O seguinte é um trecho de um livro sobre design de banco de dados (Beginning Database Design ISBN: 0-7645-7490-6):
O perigo de usar visualizações é filtrar uma consulta em uma visualização, esperando ler uma parte muito pequena de uma tabela muito grande. Qualquer filtragem deve ser feita na exibição porque qualquer filtragem na própria exibição é aplicada depois que a consulta na exibição conclui a execução. As exibições geralmente são úteis para acelerar o processo de desenvolvimento, mas, a longo prazo, podem matar completamente o desempenho do banco de dados.
O seguinte é um trecho da documentação do PostgreSQL 9.5:
Fazer uso liberal de visualizações é um aspecto fundamental do bom design de banco de dados SQL. As visualizações permitem encapsular os detalhes da estrutura de suas tabelas, que podem mudar à medida que seu aplicativo evolui, por trás de interfaces consistentes.
As duas fontes parecem se contradizer ("não projete com vistas" vs. "faça design com vistas").
No entanto, nas visualizações PG são implementadas usando o sistema de regras. Portanto, possivelmente (e esta é a minha pergunta) qualquer filtragem na exibição é reescrita como um filtro na exibição, resultando em uma única execução de consulta nas tabelas subjacentes.
Minha interpretação está correta e o PG combina cláusulas WHERE dentro e fora da visão? Ou ele os executa separadamente, um após o outro? Algum exemplo curto, autocontido, correto (compilável)?
O livro está errado.
A seleção de uma exibição é exatamente tão rápida ou lenta quanto a execução da instrução SQL subjacente – você pode verificar isso facilmente usando
explain analyze
.O otimizador do Postgres (e o otimizador para muitos outros DBMSs modernos) será capaz de empurrar predicados na visão para a instrução de visão real – desde que esta seja uma instrução simples (novamente, isso pode ser verificado usando
explain analyze
).A "má reputação" em relação ao desempenho decorre – eu acho – de quando você usa visualizações em excesso e começa a construir visualizações que usam visualizações que usam visualizações. Muitas vezes isso resulta em declarações que fazem muito em comparação com uma declaração que foi feita sob medida sem as visualizações, por exemplo, porque algumas tabelas intermediárias não seriam necessárias. Em quase todos os casos, o otimizador não é inteligente o suficiente para remover essas tabelas/junções desnecessárias ou para empurrar predicados em vários níveis de visualizações (isso também é verdade para outros SGBDs).
Para dar um exemplo do que @a_horse explicou :
O Postgres implementa o esquema de informações, que consiste em visualizações (às vezes complexas) que fornecem informações sobre objetos de banco de dados de forma padronizada. Isso é conveniente e confiável - e pode ser substancialmente mais caro do que acessar as tabelas do catálogo Postgres diretamente.
Exemplo muito simples, para obter todas as colunas visíveis de uma tabela
... do esquema de informações:
... do catálogo do sistema:
Compare os planos de consulta e o tempo de execução para ambos com o
EXPLAIN ANALYZE
.A primeira consulta é baseada na view
information_schema.columns
, que une várias tabelas que não precisamos para isso.A segunda consulta verifica apenas uma tabela
pg_catalog.pg_attribute
, portanto, muito mais rápido. (Mas a primeira consulta ainda precisa de apenas alguns ms em bancos de dados comuns.)Detalhes:
EDITAR:
Com desculpas, preciso retirar minha afirmação de que a resposta aceita nem sempre está correta - ela afirma que a visão é sempre idêntica à mesma coisa escrita como uma subconsulta. Acho que isso é indiscutível, e acho que agora sei o que está acontecendo no meu caso.
Agora também acho que há uma resposta melhor para a pergunta original.
A questão original é sobre se deve ser a prática de orientação para usar visualizações (em oposição a, por exemplo, repetir SQL em rotinas que podem precisar ser mantidas duas ou mais vezes).
Minha resposta seria "não se sua consulta usar funções de janela ou qualquer outra coisa que faça com que o otimizador trate a consulta de maneira diferente quando ela se tornar uma subconsulta, porque o próprio ato de criar a subconsulta (representada como uma visualização ou não) pode prejudicar o desempenho se você estiver filtrando com parâmetros em tempo de execução.
A complexidade da minha função de janela é desnecessária. O plano de explicação para isso:
é muito menos dispendioso do que para isso:
Espero que seja um pouco mais específico e útil.
Na minha experiência recente (fazendo com que eu encontre essa pergunta), a resposta aceita acima não está correta em todas as circunstâncias. Eu tenho uma consulta relativamente simples que inclui uma função de janela:
Se eu adicionar este filtro:
O plano de explicação que recebo é o seguinte:
Isso está usando o índice de chave primária na tabela de serviço de trem e um índice não exclusivo na tabela partition_consist. Executa em 90ms.
Eu criei uma visão (colando aqui para ficar absolutamente claro, mas é literalmente a consulta em uma visão):
Quando eu consulto essa visualização com o filtro idêntico:
Este é o plano de explicação:
Isso está fazendo varreduras completas em ambas as tabelas e leva 17s.
Até me deparar com isso, usei liberalmente as visualizações com o PostgreSQL (tendo entendido as visões amplamente aceitas expressas na resposta aceita). Eu evitaria especificamente o uso de visualizações se precisar de filtragem pré-agregada, para a qual usaria funções de retorno de conjunto.
Também estou ciente de que os CTEs no PostgreSQL são estritamente avaliados separadamente, por design, então não os uso da mesma maneira que faria com o SQL Server, por exemplo, onde eles parecem ser otimizados como subconsultas.
Minha resposta, portanto, é que há casos em que as visualizações não funcionam exatamente como a consulta na qual se baseiam, portanto, recomenda-se cautela. Estou usando o Amazon Aurora baseado no PostgreSQL 9.6.6.
(Sou um grande fã de visualizações, mas você precisa ter muito cuidado com o PG aqui e gostaria de incentivar todos a usar visualizações geralmente também no PG para melhor compreensão e manutenção de consultas/código)
Na verdade e infelizmente (AVISO:) usar visualizações no Postgres nos causou problemas reais e diminuiu muito nosso desempenho dependendo dos recursos que estávamos usando dentro dele :-( (pelo menos com v10.1 / upd: em relação à v12 veja abaixo). ( Isso não seria assim com outros sistemas de banco de dados modernos como o Oracle.)
(Dependendo do que você quer dizer exatamente - não - tabelas temporárias intermediárias podem ser materializadas que você pode não querer ou onde os predicados não são pressionados ...)
Conheço pelo menos dois grandes "recursos", que nos decepcionaram no meio das migrações do Oracle para o Postgres , então tivemos que abandonar o PG em um projeto:
CTEs ( -clause
with
subqueries / common table expression ) são (geralmente) úteis para estruturar consultas mais complexas (mesmo em aplicativos menores), mas no PG são implementados por design como dicas de otimizador "ocultas" (gerando, por exemplo, tabelas temporárias não indexadas) e violando assim o (para mim e muitos outros importantes) conceito de SQL declarativo ( Oracle docu ) ( upd 2020-08-02 : com PG v12 + esses planos de consulta de amostra devem ser os mesmos agora): por exemploconsulta simples:
reescrito usando algum CTE:
outras fontes com discussões etc.: https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/
funções de janela com
over
-instruções são potencialmente inutilizáveis (normalmente usadas em visualizações, por exemplo, como fonte de relatórios baseados em consultas mais complexas)with
-cláusulas podem funcionar desde a v12atualização 2020-08-01 : olhando para os documentos v12
with
em alguns ou todos os seus casos , há uma otimização necessária há muito tempo (mas ainda provavelmente não está funcionando se as funções da janela forem usadas lá, conforme detalhado logo acima):nossa solução alternativa para as
with
cláusulas (PG v10)Vamos transformar todas as "visualizações inline" em visualizações reais com um prefixo especial para que elas não atrapalhem a lista/namespace de visualizações e possam ser facilmente relacionadas à "visualização externa" original :-/
nossa solução para as funções da janela
Implementamos com sucesso usando o banco de dados Oracle.