A seguir, um trecho de um livro sobre design de banco de dados (ISBN: 0-7645-7490-6):
O perigo do uso de 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 dentro da visualização porque qualquer filtragem na própria visualização é aplicada após a consulta na visualização concluir a execução. As visualizações geralmente são úteis para acelerar o processo de desenvolvimento, mas a longo prazo podem prejudicar completamente o desempenho do banco de dados.
A seguir, um trecho da documentação do PostgreSQL 9.5:
Fazer uso liberal de visualizações é um aspecto essencial 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 projetar com vistas" vs. "projetar com vistas").
No entanto, nas visualizações PG, são implementadas usando o sistema de regras. Portanto, possivelmente (e essa é 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 as cláusulas WHERE dentro e fora da visualização? Ou os executa separadamente, um após o outro? Algum exemplo curto, independente, correto (compilável)?
SELECT * FROM my_view WHERE my_column = 'blablabla';
.Enquanto o segundo é sobre o uso de visualizações para tornar seu modelo de dados transparente para o aplicativo que o utiliza. As primeiras fontes apontam para você incluir o filtroWHERE my_column = 'blablabla'
dentro da definição de exibição, pois isso resulta em um melhor plano de execução.Respostas:
O livro está errado.
A seleção de uma visualização é exatamente tão rápida ou lenta quanto a execução da instrução SQL subjacente - você pode verificar isso facilmente
explain analyze
.O otimizador do Postgres (e o otimizador de muitos outros DBMSes modernos) poderá enviar os predicados da exibição para a declaração de exibição real - desde que seja uma declaraçã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 demais as visualizações e começa a criar 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 feita à mão 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 as tabelas / associações desnecessárias ou empurrar os predicados para vários níveis de visualizações (isso também é válido para outros DBMSes).
fonte
explain analyze
declaração?Para dar um exemplo do que o @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 diretamente as tabelas de catálogo do Postgres.
Exemplo muito simples, para obter todas as colunas visíveis de uma tabela
... a partir do esquema de informações:
... do catálogo do sistema:
Compare planos de consulta e tempo de execução para ambos com
EXPLAIN ANALYZE
.A primeira consulta é baseada na visualização
information_schema.columns
, que se une a 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:
fonte
EDITAR:
Com desculpas, preciso retirar minha afirmação de que a resposta aceita nem sempre é correta - ela afirma que a exibição é sempre idêntica à mesma coisa escrita como uma subconsulta. Eu acho que é 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 é se deveria ser prática orientadora o uso de visualizações (em vez de, por exemplo, repetir o SQL em rotinas que talvez precisem ser mantidas duas ou mais vezes).
Minha resposta seria "se a 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 exibiçã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 oneroso do que para isso:
Espero que seja um pouco mais específico e útil.
Na minha experiência recente (levando-me a encontrar 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ços de trem e um índice não exclusivo na tabela porção_consist. Ele é executado em 90ms.
Criei uma view (colá-la aqui para ficar absolutamente clara, mas é literalmente a consulta em uma view):
Quando eu consulto essa exibição com o filtro idêntico:
Este é o plano de explicação:
Isso faz varreduras completas nas duas tabelas e leva 17s.
Até me deparar com isso, tenho usado liberalmente visualizações com o PostgreSQL (tendo compreendido as visões amplamente expressas 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 as CTEs no PostgreSQL são rigorosamente avaliadas separadamente, por design, portanto não as uso da mesma maneira que usaria no SQL Server, por exemplo, onde elas parecem otimizadas como subconsultas.
Minha resposta, portanto, é que há casos em que os modos de exibição não funcionam exatamente como a consulta na qual eles se baseiam, portanto, recomenda-se cautela. Estou usando o Amazon Aurora com base no PostgreSQL 9.6.6.
fonte
CASE WHEN (NOT ts.primary_direction) THEN '-1' :: INTEGER ELSE 1 END
será desnecessário tornar a consulta mais lenta do que o necessário, é melhor escrever mais dois condicionais no pedido.CASE WHEN (NOT ts.primary_direction) THEN dense_rank() OVER (PARTITION BY ts.train_service_key ORDER BY pc.through_idx DESC, pc.first_portion ASC, pc.first_seq DESC) ELSE dense_rank() OVER (PARTITION BY ts.train_service_key ORDER BY pc.through_idx DESC, pc.first_portion ASC, pc.first_seq ASC) END AS coach_block_idx
dense_rank()
isso não é realmente um problema de desempenho.(Eu sou um grande fã de visualizações, mas você deve ter muito cuidado com o PG aqui e gostaria de incentivar todos a usar as visualizações geralmente também no PG para melhor compreensão e manutenção de consultas / códigos)
Na verdade, infelizmente (AVISO :) o uso de visualizações no Postgres nos causou problemas reais e diminuiu bastante nosso desempenho, dependendo dos recursos que estávamos usando dentro dele :-( (pelo menos na v10.1). (Isso não seria o caso com outras sistemas de banco de dados modernos, como o Oracle.)
(Dependendo do que você quer dizer exatamente - as tabelas temporárias intermediárias podem ser materializadas que você pode não querer estar ou onde os predicados não são pressionados para baixo ...)
Conheço pelo menos dois "recursos" principais que nos decepcionaram no meio das migrações do Oracle para o Postgres, então tivemos que abandonar o PG em um projeto:
CTEs (
with
subconsultas -clause / expressões de tabela comuns ) são (geralmente) útil para a estruturação de consultas mais complexas (mesmo em aplicações menores), mas em PG são por design implementado como "escondido" otimizador dicas (gerando por exemplo, tabelas temporárias não indexados) e viole, assim, o conceito (para mim e para muitos outros importantes) de SQL declarativo ( Oracle docu ):consulta simples:
reescrito usando algum CTE:
outras fontes com discussões etc .: https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/
as funções de janela com
over
-statements são potencialmente inutilizáveis (normalmente usadas em visualizações, por exemplo, como fonte de relatórios com base em consultas mais complexas)nossa solução alternativa para as
with
cláusulasTransformaremos 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
Nós o implementamos com sucesso usando o banco de dados Oracle.
fonte