Bisakah mendeklarasikan volatilitas fungsi membahayakan performa?

9

Fungsi Postgres dideklarasikan dengan klasifikasi volatilitas VOLATILE, STABLEatauIMMUTABLE . Proyek ini dikenal sangat ketat dengan label ini untuk fungsi bawaan. Dan dengan alasan yang bagus. Contoh yang menonjol: indeks ekspresi hanya memungkinkan IMMUTABLEfungsi dan yang harus benar-benar berubah untuk menghindari hasil yang salah.

Fungsi yang ditentukan pengguna masih bebas untuk dinyatakan sesuai keinginan pemilik. Manual menyarankan:

Untuk hasil optimalisasi terbaik, Anda harus memberi label fungsi Anda dengan kategori volatilitas paling ketat yang berlaku untuknya.

... dan menambahkan daftar luas hal-hal yang dapat salah dengan label volatilitas yang salah.

Namun, ada beberapa kasus di mana memalsukan ketidakberdayaan masuk akal. Sebagian besar ketika Anda tahu fungsinya, pada kenyataannya, tidak berubah dalam lingkup Anda. Contoh:

Selain semua implikasi yang mungkin terjadi pada integritas data , apa efeknya terhadap kinerja? Orang mungkin berasumsi bahwa mendeklarasikan fungsi IMMUTABLEhanya dapat bermanfaat bagi kinerja . Apakah begitu?

Bisakah mendeklarasikan volatilitas fungsi IMMUTABLE merusak kinerja?

Mari kita asumsikan Postgres 10 saat ini untuk mempersempitnya, tetapi semua versi terbaru menarik.

Erwin Brandstetter
sumber
1
Sebagai catatan tambahan juga, keseluruhan "benar-benar tidak berubah" pada indeks ekspresi adalah pita nyata. Itu UI yang mengerikan. Kita harus bisa melakukan FORCEkeduanya. 100% dari DBA PostgreSQL berpengalaman berbohong untuk mengerjakan UI itu dengan fungsi wrapper. Setidaknya dengan FORCE, kita tidak perlu pembungkus dan kita tidak perlu berbohong pada volatilitas yang diumumkan.
Evan Carroll
1
Saya berasumsi FORCEseharusnya membuat indeks ekspresi menerima fungsi yang tidak dapat diubah (sambil menandainya sebagai titik kegagalan potensial). Ya, itu akan tampak seperti solusi yang lebih elegan daripada pembungkus fungsi yang tidak berubah.
Erwin Brandstetter
Saya hampir tidak tahu tentang PostGres tetapi bukankah volatilitas tidak stabil? Apa artinya? Serius jangan berharap ini bisa diandalkan, karena ini gila ?
Anthony
@Anthony: Saya mengklarifikasi lebih banyak lagi. Ikuti tautan ke manual untuk detailnya.
Erwin Brandstetter

Jawaban:

7

Ya, itu dapat merusak kinerja.

Fungsi SQL sederhana dapat "disejajarkan" dalam permintaan panggilan. Mengutip Postgres Wiki :

Fungsi SQL (yaitu LANGUAGE SQL) akan, dalam kondisi tertentu, memiliki fungsi tubuh mereka diikutkan ke dalam permintaan panggilan daripada dipanggil secara langsung. Ini dapat memiliki keuntungan kinerja yang substansial karena fungsi tubuh menjadi terpapar pada perencana permintaan panggilan, yang dapat menerapkan optimisasi seperti pelipatan konstan, penurunan kualitas, dan sebagainya.

Penekanan berani saya.

Untuk menegakkan kebenaran, ada sejumlah prasyarat. Salah satunya :

jika fungsi tersebut dideklarasikan IMMUTABLE, maka ekspresi tidak boleh memanggil fungsi atau operator yang tidak dapat diubah

Artinya, fungsi SQL menggunakan fungsi yang tidak dapat diubah tetapi masih dinyatakan IMMTUTABLEtidak termasuk dalam optimasi ini. Dipicu oleh jawaban terkait ini di SO, saya telah menjalankan tes ekstensif:

Pada dasarnya membandingkan dua varian fungsi SQL sederhana ini (memetakan tanggal ke integer, mengabaikan tahun yang tidak penting untuk tujuan tersebut):

CREATE FUNCTION f_mmdd_tc_s(date) RETURNS int LANGUAGE sql STABLE    AS
$$SELECT to_char($1, 'MMDD')::int$$;

CREATE FUNCTION f_mmdd_tc_i(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT to_char($1, 'MMDD')::int$$;  -- cannot be inlined!

Fungsi Postgres to_char()saja STABLE, bukan IMMUTABLE(semua contoh kelebihan - karena alasan di luar cakupan jawaban ini ). Jadi yang kedua palsu IMMUTABLEdan ternyata 5x lebih lambat dalam tes sederhana:

db <> biola di sini

Contoh spesifik ini dapat diganti dengan yang setara:

CREATE FUNCTION f_mmdd(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT (EXTRACT(month FROM $1) * 100 + EXTRACT(day FROM $1))::int$$;

Akan tampak lebih mahal dengan dua panggilan fungsi dan lebih banyak perhitungan. Tapi IMMUTABLElabel ini benar (ditambah, fungsi yang digunakan lebih cepat dan memaksa textuntuk integerlebih mahal, juga).

2x lebih cepat dari varian tercepat di atas (10x lebih cepat dari yang lebih lambat). Intinya adalah: Gunakan IMMUTABLEfungsi jika memungkinkan , maka Anda tidak perlu "menipu" untuk memulai.

Erwin Brandstetter
sumber
Temuan keren! Dapatkan tindak lanjut segera untuk itu: dba.stackexchange.com/q/212198/2639
Evan Carroll
Anda tahu apa yang saya pikir saya lewatkan di sini, yang saya tidak tahu. Itu STABLEjuga sejajar. Saya pikir pengoptimal hanya akan IMMUTABLEfungsi online .
Evan Carroll
VOLATILEjuga.
Erwin Brandstetter
Wiki mengatakan bahwa fungsi tersebut dinyatakan STABIL atau IMMUTABLE wiki.postgresql.org/wiki/Inlining_of_SQL_functions
Evan Carroll
.. di bawah "Kondisi sebaris untuk fungsi tabel ". Bukan untuk fungsi skalar. Saya menunjukkannya di biola: dbfiddle.uk/…
Erwin Brandstetter