Nel post del blog di Bruce Momjian Generating Random Data Via SQL ha usato il seguente codice per generare 5 stringhe casuali:PostgreSQL espressioni volatili e subquery
SELECT
(
SELECT string_agg(x, '')
FROM (
SELECT chr(ascii('a') + floor(random() * 26)::integer)
FROM generate_series(1, 40 + b * 0) as f(g)
) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);
result
------------------------------------------
plwfwcgajxdygfissmxqsywcwiqptytjjppgrvgb
sjaypirhuoynnvqjdgywfsfphuvzqbbilbhakyhf
ngtabkjfqibwahlicgisijatliuwgbcuiwujgeox
mqtnyewalettounachwjjzdrvxbbbpzogscexyfi
dzcstpsvwpefohwkfxmhnlwteyybxejbdltwamsx
(5 rows)
mi sono chiesto perché 'b * 0' at line 6 è richiesto. Quando l'ho rimosso, il risultato è stato modificato in 5 stringhe esattamente simili, il che significa che Postgres ha memorizzato nella cache l'espressione di selezione esterna (risultato)!
Non sono riuscito a trovare il modo in cui la cache di espressione funziona in Postgres. Secondo the documentation la funzione random() è contrassegnata VOLATILE, quindi, mi aspetto che anche qualsiasi espressione dipenda da essa sia volatile.
Come funziona il caching delle espressioni in Postgres? È documentato da qualche parte? Perché 'b * 0' disabilita la cache dove random() no?
Aggiornamento:
per studiare la questione, mi sono trasferito 'b * 0' all'interno del piano() chiamata per essere alla stessa posizione/livello come casuale():
...
SELECT chr(ascii('a') + floor(random() * 26 + b * 0)::integer)
FROM generate_series(1, 40) as s(f)
...
Il risultato non è ancora stato memorizzato nella cache; stringhe diverse.
Update: Un altro esempio per mostrare il problema
create sequence seq_test;
SELECT (SELECT nextval('seq_test')) FROM generate_series(1,5);
?column?
----------
1
1
1
1
1
(5 rows)
Quindi, il planner ha valutato l'espressione interna per ogni riga 'f' nonostante non dipendesse da esso (correttamente perché è volatile), ma l'espressione esterna viene valutata una volta a meno che non dipenda dalla riga! Non dovrebbero i valori volatili tintare alcun risultato basato su di esso? proprio come faceva la dipendenza dalla riga. –
la volatilità dell'espressione interromperà la sua inclinazione, ma non influisce sul modo in cui il pianificatore organizza il piano di query, che si basa sul fatto che la sottoselezione sia correlata o meno. – araqnid
Vuoi dire che ogni subquery è considerata STABILE a meno che non dipenda dalla variabile di riga della query esterna! Mi sembra un insetto. Mi aspetto che le espressioni volatili abbiano un effetto virale di volatilità su qualsiasi espressione o sottoquery. InitPlan è un'ottimizzazione, non dovrebbe modificare il risultato. –