MODIFICARE:
Con scuse, ho bisogno di ritirare la mia affermazione che la risposta accettata non è sempre corretta - afferma che la vista è sempre identica alla stessa cosa scritta come una sottoquery. Penso che sia indiscutibile, e ora penso di sapere cosa sta succedendo nel mio caso.
Ora penso anche che ci sia una risposta migliore alla domanda originale.
La domanda originale è se dovrebbe essere la guida pratica ad usare le viste (al contrario, ad esempio, di ripetere SQL nelle routine che potrebbero dover essere mantenute due o più volte).
La mia risposta sarebbe "no se la tua query utilizza funzioni di finestra o qualsiasi altra cosa che induca l'ottimizzatore a trattare la query in modo diverso quando diventa una sottoquery, perché l'atto stesso di creare la sottoquery (rappresentata come vista o meno) può ridurre le prestazioni se si sta filtrando con parametri in fase di esecuzione.
La complessità della mia funzione finestra non è necessaria. Il piano esplicativo per questo:
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';
è molto meno costoso rispetto a questo:
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';
Spero che sia un po 'più specifico e utile.
Nella mia recente esperienza (che mi ha fatto trovare questa domanda), la risposta accettata sopra non è corretta in tutte le circostanze. Ho una query relativamente semplice che include una funzione di finestra:
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 aggiungo questo filtro:
where assembly_key = '185132'
Il piano esplicativo che ottengo è il seguente:
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))
Questo utilizza l'indice della chiave primaria nella tabella dei servizi del treno e un indice non univoco nella tabella porzione_consist. Si esegue in 90ms.
Ho creato una vista (incollandola qui per essere assolutamente chiara ma è letteralmente la query in una vista):
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 eseguo una query su questa vista con lo stesso filtro:
select * from staging.v_unit_coach_block
where assembly_key = '185132';
Questo è il piano esplicativo:
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)
Questo esegue scansioni complete su entrambi i tavoli e richiede 17 secondi.
Fino a quando non mi sono imbattuto in questo, ho usato liberamente le opinioni con PostgreSQL (avendo compreso le opinioni ampiamente espresse nella risposta accettata). In particolare, eviterei di usare le viste se avessi bisogno di un filtro pre-aggregato, per il quale userei le funzioni di restituzione del set.
Sono anche consapevole che i CTE in PostgreSQL sono rigorosamente valutati separatamente, in base alla progettazione, quindi non li uso come farei con SQL Server, ad esempio, dove sembrano essere ottimizzati come sottoquery.
La mia risposta, quindi, è che ci sono casi in cui le viste non funzionano esattamente come la query su cui sono basate, quindi si consiglia cautela. Sto usando Amazon Aurora basato su PostgreSQL 9.6.6.
SELECT * FROM my_view WHERE my_column = 'blablabla';
mentre il secondo riguarda l'uso delle viste per rendere trasparente il modello di dati all'applicazione che lo utilizza. Le prime fonti indicano di includere il filtroWHERE my_column = 'blablabla'
all'interno della definizione della vista, in quanto ciò risulta in un piano di esecuzione migliore.