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:
SELECT DISTINCT ts.train_service_key,
pc.assembly_key,
count(*) OVER
(PARTITION BY ts.train_service_key) AS train_records
FROM staging.train_service ts
JOIN staging.portion_consist pc
USING (ds_code, train_service_key)
WHERE assembly_key = '185132';
é muito menos oneroso do que para isso:
SELECT *
FROM (SELECT DISTINCT ts.train_service_key,
pc.assembly_key,
count(*) OVER
(PARTITION BY ts.train_service_key) AS train_records
FROM staging.train_service ts
JOIN staging.portion_consist pc
USING (ds_code, train_service_key)) AS query
WHERE assembly_key = '185132';
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:
SELECT DISTINCT ts.train_service_key,
pc.assembly_key,
dense_rank() OVER (PARTITION BY ts.train_service_key
ORDER BY pc.through_idx DESC, pc.first_portion ASC,
((CASE WHEN (NOT ts.primary_direction)
THEN '-1' :: INTEGER
ELSE 1
END) * pc.first_seq)) AS coach_block_idx
FROM (staging.train_service ts
JOIN staging.portion_consist pc USING (ds_code, train_service_key))
Se eu adicionar este filtro:
where assembly_key = '185132'
O plano de explicação que recebo é o seguinte:
QUERY PLAN
Unique (cost=11562.66..11568.77 rows=814 width=43)
-> Sort (cost=11562.66..11564.70 rows=814 width=43)
Sort Key: ts.train_service_key, (dense_rank() OVER (?))
-> WindowAgg (cost=11500.92..11523.31 rows=814 width=43)
-> Sort (cost=11500.92..11502.96 rows=814 width=35)
Sort Key: ts.train_service_key, pc.through_idx DESC, pc.first_portion, ((CASE WHEN (NOT ts.primary_direction) THEN '-1'::integer ELSE 1 END * pc.first_seq))
-> Nested Loop (cost=20.39..11461.57 rows=814 width=35)
-> Bitmap Heap Scan on portion_consist pc (cost=19.97..3370.39 rows=973 width=38)
Recheck Cond: (assembly_key = '185132'::text)
-> Bitmap Index Scan on portion_consist_assembly_key_index (cost=0.00..19.72 rows=973 width=0)
Index Cond: (assembly_key = '185132'::text)
-> Index Scan using train_service_pk on train_service ts (cost=0.43..8.30 rows=1 width=21)
Index Cond: ((ds_code = pc.ds_code) AND (train_service_key = pc.train_service_key))
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):
CREATE OR REPLACE VIEW staging.v_unit_coach_block AS
SELECT DISTINCT ts.train_service_key,
pc.assembly_key,
dense_rank() OVER (PARTITION BY ts.train_service_key
ORDER BY pc.through_idx DESC, pc.first_portion ASC, (
(CASE
WHEN (NOT ts.primary_direction)
THEN '-1' :: INTEGER
ELSE 1
END) * pc.first_seq)) AS coach_block_idx
FROM (staging.train_service ts
JOIN staging.portion_consist pc USING (ds_code, train_service_key))
Quando eu consulto essa exibição com o filtro idêntico:
select * from staging.v_unit_coach_block
where assembly_key = '185132';
Este é o plano de explicação:
QUERY PLAN
Subquery Scan on v_unit_coach_block (cost=494217.13..508955.10 rows=3275 width=31)
Filter: (v_unit_coach_block.assembly_key = '185132'::text)
-> Unique (cost=494217.13..500767.34 rows=655021 width=43)
-> Sort (cost=494217.13..495854.68 rows=655021 width=43)
Sort Key: ts.train_service_key, pc.assembly_key, (dense_rank() OVER (?))
-> WindowAgg (cost=392772.16..410785.23 rows=655021 width=43)
-> Sort (cost=392772.16..394409.71 rows=655021 width=35)
Sort Key: ts.train_service_key, pc.through_idx DESC, pc.first_portion, ((CASE WHEN (NOT ts.primary_direction) THEN '-1'::integer ELSE 1 END * pc.first_seq))
-> Hash Join (cost=89947.40..311580.26 rows=655021 width=35)
Hash Cond: ((pc.ds_code = ts.ds_code) AND (pc.train_service_key = ts.train_service_key))
-> Seq Scan on portion_consist pc (cost=0.00..39867.86 rows=782786 width=38)
-> Hash (cost=65935.36..65935.36 rows=1151136 width=21)
-> Seq Scan on train_service ts (cost=0.00..65935.36 rows=1151136 width=21)
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.
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.