Saya mencoba memahami dampak kinerja memilih data dari tampilan, di mana salah satu kolom dalam tampilan adalah fungsi dari data lain dalam tabel asli.
Apakah perhitungan dilakukan terlepas dari apakah kolom yang dihitung ada dalam daftar kolom yang dipilih atau tidak?
Jika saya punya meja dan tampilan dinyatakan seperti itu
CREATE TABLE price_data (
ticker text, -- Ticker of the stock
ddate date, -- Date for this price
price float8, -- Closing price on this date
factor float8 -- Factor to convert this price to USD
);
CREATE VIEW prices AS
SELECT ticker,
ddate,
price,
factor,
price * factor as price_usd
FROM price_data
Akankah bahwa perkalian dilakukan di query seperti di bawah?
select ticker, ddate, price, factor from prices
Apakah ada referensi yang menjamin cara ini atau yang lain? Saya membaca dokumentasi tentang sistem aturan di Postgres, tetapi saya pikir jawabannya benar-benar terletak pada optimiser, karena tidak ada dalam dokumentasi sistem aturan yang menunjukkan bahwa itu tidak akan dipilih.
Saya menduga dalam kasus di atas perhitungan tidak dilakukan. Saya mengubah pandangan ke divisi penggunaan bukan perkalian, dan memasukkan 0
untuk factor
menjadi price_data
. Kueri di atas tidak gagal, tetapi jika kueri dimodifikasi untuk memilih kolom yang dihitung kueri yang diubah gagal.
Apakah ada cara untuk memahami perhitungan apa yang sedang dilakukan ketika a select
dilakukan? Saya kira saya sedang mencari sesuatu seperti EXPLAIN
tetapi yang juga memberitahu saya tentang perhitungan yang dilakukan.
sumber
Jawaban:
Seperti yang dikatakan @Laurenz, analisis Anda benar: pengoptimal akan menghindari mengevaluasi ekspresi kolom yang tidak memengaruhi hasil kueri (dan upaya Anda untuk memaksakan kesalahan divide-by-zero adalah buktinya).
Ini tergantung pada kolom mana yang Anda pilih, tetapi juga tergantung pada kategori volatilitas dari ekspresi kolom. Pengoptimal bebas untuk dihilangkan
immutable
danstable
panggilan fungsi jika output mereka tidak pernah digunakan, karena mereka tidak dapat mempengaruhi hasil, tetapivolatile
fungsi mungkin memiliki efek samping, sehingga mereka tidak begitu mudah dioptimalkan.Sebagai contoh:
Jika hanya
volatile
kolom yang dipilih:... maka seperti yang Anda lihat,
stable_function()
tidak ada dalamexplain
output, dan tidak adanyaNOTICE
konfirmasi bahwa panggilan ini telah dioptimalkan.Namun, jika
stable
kolom yang dipilih sebagai gantinya:... lalu kita melihat kedua ekspresi kolom muncul dalam rencana, dan
NOTICE
s menunjukkan bahwa kedua fungsi telah dieksekusi.Tampaknya tidak ada penyebutan eksplisit perilaku ini dalam dokumen, jadi tidak ada jaminan keras mengenai apakah ekspresi akan dievaluasi, dan Anda tidak boleh mengandalkan efek samping apa pun yang mungkin dimiliki oleh panggilan fungsi Anda.
Tetapi jika satu-satunya masalah Anda adalah kinerja, maka selama Anda menandai fungsi Anda sebagai
stable
atau diimmutable
mana sesuai, Anda dapat yakin (terutama dalam kasus-kasus sederhana seperti ini) bahwa mereka tidak akan dievaluasi kecuali mereka diperlukan.(Dan saat Anda di sana mengaudit deklarasi volatilitas Anda, Anda mungkin ingin mengatur bendera keselamatan paralel juga.)
sumber
Kecurigaan Anda benar, dan perhitungan tidak boleh dilakukan jika kolom tidak digunakan.
Untuk mengonfirmasi itu, lihat output
EXPLAIN (VERBOSE)
untuk kueri, yang akan menampilkan kolom yang dikembalikan.sumber