PostgreSQL: Immutable, Volatile, Stable

11

Saya tidak jelas tentang arti sebenarnya dalam definisi untuk fungsi IMMUTABLE, VOLATILE dan STABLE.

Saya membaca dokumentasi, khususnya definisi masing-masing.

IMMUTABLE menunjukkan bahwa fungsi tidak dapat memodifikasi database dan selalu mengembalikan hasil yang sama ketika diberi nilai argumen yang sama ; yaitu, ia tidak melakukan pencarian basis data atau menggunakan informasi yang tidak secara langsung hadir dalam daftar argumennya. Jika opsi ini diberikan, panggilan fungsi apa pun dengan argumen semua-konstan dapat segera diganti dengan nilai fungsi.

STABEL menunjukkan bahwa fungsi tidak dapat memodifikasi database, dan bahwa dalam pemindaian tabel tunggal akan secara konsisten mengembalikan hasil yang sama untuk nilai argumen yang sama , tetapi hasilnya dapat berubah di seluruh pernyataan SQL. Ini adalah pilihan yang sesuai untuk fungsi yang hasilnya tergantung pada pencarian basis data, variabel parameter (seperti zona waktu saat ini), dll. (Tidak sesuai untuk pemicu SETELAH yang ingin meminta baris yang dimodifikasi oleh perintah saat ini.) Juga perhatikan bahwa current_timestamp keluarga fungsi memenuhi syarat sebagai stabil, karena nilainya tidak berubah dalam suatu transaksi.

VOLATILE menunjukkan bahwa nilai fungsi dapat berubah bahkan dalam satu pemindaian tabel, jadi tidak ada optimasi yang dapat dilakukan. Dalam beberapa hal fungsi database relatif tidak stabil; beberapa contoh acak (), currval (), timeofday (). Tetapi perhatikan bahwa setiap fungsi yang memiliki efek samping harus diklasifikasikan volatil, meskipun hasilnya cukup dapat diprediksi, untuk mencegah panggilan dioptimalkan; contohnya adalah setval ().

Kebingungan saya datang dengan kondisi untuk IMMUTABLE dan STABLE bahwa fungsi SELALU atau KONSISTEN mengembalikan hasil yang sama diberikan argumen yang sama.

Definisi IMMUTABLE menyatakan bahwa fungsi tersebut tidak mencari basis data atau menggunakan informasi yang tidak secara langsung hadir dalam daftar argumennya. Jadi, bagi saya, itu berarti fungsi seperti itu digunakan untuk memanipulasi data yang disediakan oleh klien, dan seharusnya tidak memiliki pernyataan SELECT ... walaupun itu kedengarannya agak aneh bagi saya.

Dengan STABLE, definisi ini serupa dengan yang dikatakannya harus konsisten mengembalikan hasil yang sama. Jadi, bagi saya, itu berarti bahwa setiap kali fungsi dipanggil dengan argumen yang sama, itu harus mengembalikan hasil yang sama (baris persis sama, setiap saat).

Jadi, bagi saya ... itu berarti bahwa setiap fungsi yang melakukan SELECT pada tabel atau tabel yang dapat diperbarui, seharusnya hanya volatile.

Tapi, sekali lagi ... itu kedengarannya tidak benar bagiku.

Membawa ini kembali ke kasus penggunaan saya, saya menulis fungsi yang melakukan pernyataan SELECT dengan beberapa GABUNG pada tabel yang terus-menerus ditambahkan, sehingga pemanggilan fungsi diharapkan untuk mengembalikan hasil yang berbeda setiap kali dipanggil, bahkan dengan argumen yang sama .

Jadi, apakah itu berarti bahwa fungsi saya harus VOLATILE? Meskipun dokumentasi menunjukkan fungsi database relatif sedikit volatile dalam pengertian ini ?

Terima kasih!

Anak sungai
sumber

Jawaban:

15

IMMUTABLEharus merupakan fungsi murni, yang hasilnya hanya bergantung pada inputnya. Ini adalah persyaratan yang sangat ketat; mereka tidak dapat memanggil fungsi-fungsi lain yang tidak dapat diubah, mereka tidak dapat mengakses tabel, mereka tidak dapat mengakses nilai properti konfigurasi, dll.

STABLEdapat menggunakan input apa pun itu sendiri STABLE: fungsi STABLEatau lainnya IMMUTABLE, dan SELECTkueri tabel. Aman untuk kueri tabel karena tampilan fungsi dari tabel tersebut tidak akan berubah dalam snapshot saat ini. Anda dapat mengakses nilai GUC ( current_setting(...)) selama Anda tahu mereka tidak akan ditugaskan dalam pernyataan saat ini.

VOLATILE fungsi adalah semua yang tidak sesuai dengan di atas:

  • Apa pun dengan efek samping
  • Apa pun yang menulis
  • Apa pun yang menanyakan data eksternal yang tidak dikelola oleh snapshot PostgreSQL
  • ...

Secara umum, tinggalkan semuanya VOLATILEkecuali Anda punya alasan kuat untuk tidak melakukannya.

Alasan utama untuk digunakan IMMUTABLEadalah ketika menulis fungsi yang akan digunakan sebagai bagian dari ekspresi indeks.

Craig Ringer
sumber
1
"mereka tidak dapat mengakses tabel." Dalam keadilan, mereka dapat dan mereka melakukannya. Saya pikir aturan yang lebih umum adalah bahwa tabel tidak seharusnya bermutasi secara bermakna tanpa restart database.
Evan Carroll
Jika STABLE memungkinkan akses tabel, apakah ada optimasi di atas / di atas VOLATILE ...?
Brooks
Jangan ingat dari atas kepala saya, harus memeriksa dokumen / kode.
Craig Ringer
4

Untuk STABLE, bagian yang Anda harus cetak tebal adalah 'hasilnya bisa berubah di seluruh pernyataan SQL'

Hal-hal yang tidak dapat diubah tidak seharusnya berubah. Bahkan jika Anda me-restart Anda server database, run yum update(tapi tentu saja bisa ada bug!), Mengubah konfigurasi Anda (seperti datestyle, timezone, default_text_search_config, extra_float_digits, dll), atau mengganti hardware server Anda sepenuhnya (dari arsitektur yang sama dengan hardware lama, sehingga file biner masih kompatibel).

Fungsi-fungsi yang Anda gambarkan terdengar seperti STABIL, karena dalam satu pernyataan SQL, mereka akan mengeksekusi kueri mereka menggunakan snapshot yang sama seperti yang dimiliki oleh kueri luar, dan setiap perubahan bersamaan yang Anda buat pada tabel lainnya tidak akan terlihat. Sekarang, jika fungsi Anda membuka koneksi baru ke server dan menjalankan kueri mereka di dalam koneksi independen itu, itu akan membuat fungsi tersebut tidak stabil, karena mereka akan menggunakan snapshot yang berbeda.

jjanes
sumber
Saya percaya saya memahami prasyarat untuk IMMUTABLE (tidak ada yang bisa berubah .... pernah, antara pertanyaan, koneksi, reboot, kehancuran planet dan rekonstruksi, BAHKAN JIKA database diubah) dan VOLATILE (fungsi melompat keluar dari konteks dalam yang disebut). Apakah itu benar? Jadi, maka muncul STABEL berarti fungsi tidak mengubah database dan tidak mengakses database di luar konteksnya? Definisi STABLE terasa seperti CARA yang lebih rumit daripada yang seharusnya ... Atau apakah saya meninggalkan sesuatu?
Brooks
PostgreSQL sebenarnya memiliki beberapa masalah di sekitar IMMUTABLEdan pengumpulan. Ini percaya bahwa glibc(atau, dalam Pg yang lebih baru, iconv) tidak akan mengubah definisi susunan. Pada kenyataannya, mereka melakukannya, dan tidak memberikan cara untuk mendeteksi perubahan tersebut. Ini dapat menyebabkan korupsi indeks diam :(. Ini sebagian besar masalah ketika mereplikasi antara versi OS yang berbeda, dll.
Craig Ringer