Antipattern PostgreSQL: memerangi gerombolan "mati"

Keistimewaan mekanisme dalaman PostgreSQL membolehkannya menjadi sangat pantas dalam sesetengah situasi dan "tidak terlalu pantas" dalam situasi lain. Hari ini kita akan menumpukan pada contoh klasik konflik antara cara DBMS berfungsi dan perkara yang dilakukan oleh pembangun dengannya - KEMASKINI vs prinsip MVCC.

Cerita ringkas daripada artikel yang hebat:

Apabila baris diubah suai oleh perintah KEMASKINI, dua operasi sebenarnya dilakukan: PADAM dan INSERT. DALAM versi semasa rentetan xmax ditetapkan sama dengan bilangan transaksi yang melakukan KEMASKINI. Kemudian ia dicipta versi baru baris yang sama; nilai xminnya bertepatan dengan nilai xmax versi sebelumnya.

Beberapa ketika selepas transaksi ini selesai, versi lama atau baharu, bergantung pada COMMIT/ROOLBACK, akan diiktiraf "mati" (tuple 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 besar-besaran dalam meja besar, dan sedikit kemudian anda akan menghadapi situasi yang sama VACUUM tidak akan dapat membantu.

#1: Saya Suka Memindahkannya

Katakan kaedah anda berfungsi pada logik perniagaan, dan tiba-tiba ia menyedari bahawa adalah perlu untuk mengemas kini medan X dalam beberapa rekod:

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

Kemudian, apabila pelaksanaan berlangsung, ternyata medan Y juga harus dikemas kini:

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

... dan kemudian juga Z - mengapa membuang masa dengan perkara remeh?

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

Berapa banyak versi rekod ini yang kita ada sekarang dalam pangkalan data? Ya, 4 keping! Daripada jumlah ini, satu adalah berkaitan dan 3 perlu dibersihkan selepas anda dengan [auto]VACUUM.

Jangan lakukan dengan cara ini! guna 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 penggunaan skrip atau penukar, contohnya). Dan sesuatu seperti ini masuk ke dalam skrip:

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

Permintaan dalam lebih kurang borang ini berlaku agak kerap dan hampir selalu bukan untuk mengisi medan baharu yang kosong, tetapi untuk membetulkan beberapa ralat dalam data. Pada masa yang sama, dia sendiri ketepatan data sedia ada tidak diambil kira sama sekali - tetapi sia-sia! Iaitu, rekod itu ditulis semula, walaupun ia mengandungi apa yang dikehendaki - tetapi mengapa? 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 kekasih saya dengan... menyekat

sedang dilancarkan dua proses selari yang sama, yang setiap satunya cuba menandakan entri bahawa ia "sedang dijalankan":

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

Walaupun proses ini sebenarnya melakukan perkara yang bebas antara satu sama lain, tetapi dalam ID yang sama, pelanggan kedua akan "dikunci" pada 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, permintaan kedua tidak akan mengubah apa-apa dalam pangkalan data, semuanya sudah seperti yang sepatutnya - oleh itu, penyekatan tidak akan berlaku. Seterusnya, kami memproses fakta "tidak mencari" rekod dalam algoritma yang digunakan.

Penyelesaian #2: kunci nasihat

Topik besar untuk artikel berasingan, yang boleh anda baca kaedah penggunaan dan "rake" penyekatan cadangan.

Penyelesaian #3: panggilan bodoh

Tetapi inilah yang sepatutnya berlaku kepada anda kerja serentak dengan rekod yang sama? Atau adakah anda keliru dengan algoritma untuk memanggil logik perniagaan di sisi pelanggan, sebagai contoh? Dan jika anda memikirkannya?..

Sumber: www.habr.com

Tambah komen