Antipattern PostgreSQL: memerangi gerombolan "mati"

Cara mekanisme dalaman PostgreSQL berfungsi membolehkannya menjadi sangat pantas dalam sesetengah situasi dan tidak begitu pantas dalam situasi lain. Hari ini, kita akan melihat contoh klasik konflik antara cara DBMS berfungsi dan perkara yang dilakukan oleh pembangun dengannya: KEMASKINI lwn prinsip MVCC.

Plot ringkas daripada artikel yang sangat baik:

Apabila baris diubah suai oleh perintah KEMASKINI, dua operasi sebenarnya dilakukan: DELETE dan INSERT. versi semasa baris xmax ditetapkan kepada nombor transaksi yang melakukan KEMASKINI. Kemudian ia dicipta versi baru baris yang sama; nilai xminnya sepadan dengan nilai xmax versi sebelumnya.

Beberapa ketika selepas transaksi ini selesai, versi lama atau baharu, bergantung pada COMMIT/ROOLBACK, akan diiktiraf tupel mati apabila berlalu VACUUM mengikut jadual dan dibersihkan.

Antipattern PostgreSQL: memerangi gerombolan "mati"

Tetapi ini tidak akan berlaku serta-merta, tetapi masalah dengan "mati" boleh diperolehi dengan cepat - dengan berulang atau kemas kini rekod secara beramai-ramai dalam meja besar, dan sedikit kemudian menghadapi situasi yang VACUUM tidak akan dapat membantu.

#1: Saya Suka Memindahkannya

Katakan kaedah logik perniagaan anda sedang berjalan dan tiba-tiba menyedari bahawa ia perlu mengemas kini medan X dalam beberapa rekod:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Kemudian, apabila pelaksanaan berlangsung, ia mendapati bahawa medan Y juga perlu dikemas kini:

UPDATE tbl SET Y = <newY> WHERE pk = $1;

…dan kemudian ada juga Z – kenapa perlu bersusah payah dengan perkara kecil?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

Berapa banyak versi entri ini yang kini ada dalam pangkalan data? Ya, empat! Satu daripadanya adalah terkini dan tiga perlu dibersihkan dengan [auto]VACUUM.

Jangan buat begitu! Gunakannya! mengemas kini semua medan dalam satu permintaan — hampir selalu logik kaedah boleh diubah seperti ini:

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

#2: Penggunaan ADALAH BERBEZA DARI, Luke!

Jadi, anda masih mahu kemas kini banyak, banyak rekod dalam jadual (semasa menggunakan skrip atau penukar, sebagai contoh). Dan sesuatu seperti ini dimasukkan ke dalam skrip:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Permintaan lebih kurang borang ini ditemui agak kerap dan hampir selalu bukan untuk mengisi medan kosong baharu, tetapi untuk membetulkan beberapa ralat dalam data. ketepatan data sedia ada tidak diambil kira sama sekali - tetapi sia-sia! Iaitu, entri itu ditulis semula, walaupun ia mengandungi apa yang saya mahukan-tetapi mengapa perlu bersusah payah? Mari kita betulkan:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Ramai orang tidak menyedari kewujudan pengendali yang begitu hebat, jadi berikut adalah helaian tipu IS DISTINCT FROM dan pengendali logik lain untuk membantu:
Antipattern PostgreSQL: memerangi gerombolan "mati"
…dan sedikit tentang operasi di kompleks ROW()-ungkapan:
Antipattern PostgreSQL: memerangi gerombolan "mati"

#3: Saya mengenali sayang saya dengan... menyekat

sedang dilancarkan dua proses selari yang sama, setiap satunya cuba menandakan rakaman sebagai "sedang berjalan":

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Walaupun proses ini melaksanakan tugas bebas, tetapi dalam ID yang sama, pelanggan kedua akan "dikunci" atas permintaan ini sehingga transaksi pertama selesai.

Penyelesaian #1: tugas dikurangkan kepada yang sebelumnya

Mari tambah lagi IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

Dalam borang ini, pertanyaan kedua tidak akan mengubah apa-apa dalam pangkalan data; semuanya sudah "seperti yang sepatutnya"—jadi tiada sekatan akan berlaku. Fakta bahawa rekod "tidak dijumpai" kemudiannya dikendalikan dalam algoritma aplikasi.

Penyelesaian #2: kunci nasihat

Ini adalah topik besar untuk artikel berasingan, di mana anda boleh membaca tentangnya. Kaedah permohonan dan perangkap menyekat nasihat.

Penyelesaian #3: panggilan bodoh

Tetapi inilah yang sepatutnya berlaku kepada anda. kerja serentak dengan rekod yang samaAtau mungkin anda mengacaukan algoritma panggilan logik perniagaan pihak pelanggan, sebagai contoh? Tapi kalau difikirkan balik...

Sumber: www.habr.com