Saya menjalankan query Postgres bersamaan seperti ini:
UPDATE foo SET bar = bar + 1 WHERE baz = 1234
Setiap kueri memengaruhi jumlah baris K yang tetap, dan saya tidak dapat menemukan cara untuk menegakkan urutan pembaruan baris, saya berakhir dengan deadlock. Saat ini saya memperbaiki masalah dengan menegakkan pesanan dengan tangan, tetapi ini berarti saya harus mengeksekusi lebih banyak permintaan daripada yang biasanya saya lakukan sambil juga meningkatkan kompleksitas pencarian dari O (log N + K) ke O (K log N).
Apakah ada cara untuk meningkatkan kinerja tanpa berakhir rentan terhadap kebuntuan? Saya menduga bahwa mengganti (baz)
indeks dengan (baz, id)
indeks mungkin berhasil asalkan Postgres memperbarui baris dalam urutan yang sama dengan yang telah memindai mereka, apakah ini pendekatan yang layak untuk dilakukan?
sumber
CREATE TABLE
kode.Jawaban:
Tidak ada
ORDER BY
dalamSQL UPDATE
perintah. Baris pembaruan Postgres dalam urutan acak:Untuk menghindari kebuntuan dengan kepastian absolut, Anda bisa menjalankan laporan Anda dalam isolasi transaksi serial . Tapi itu lebih mahal dan Anda perlu bersiap untuk mengulangi perintah pada kegagalan serialisasi.
Tindakan terbaik Anda mungkin adalah untuk mengunci secara eksplisit dengan
SELECT ... ORDER BY ... FOR UPDATE
dalam subquery atau standaloneSELECT
dalam transaksi - di tingkat isolasi "baca komitmen" default. Mengutip Tom Lane di pgsql-general :Ini harus melakukan pekerjaan:
Indeks multikolom aktif
(baz, bar)
mungkin sempurna untuk kinerja. Tetapi karenabar
jelas banyak diperbarui , indeks satu kolom pada(baz)
mungkin bahkan lebih baik. Tergantung pada beberapa faktor. Berapa banyak baris perbaz
? Apakah pembaruan HOT dimungkinkan tanpa indeks multikolom? ...Jika
baz
diperbarui secara bersamaan, masih ada kemungkinan kasus sudut untuk konflik (per dokumentasi) :Juga, jika Anda harus memiliki kendala unik yang melibatkan
bar
, pertimbangkanDEFERRABLE
kendala untuk menghindari pelanggaran unik dalam perintah yang sama. Jawaban terkait:sumber
id
atau kolom unik lainnya, bukanbar
, seharusnya tidak ada sudut atau hit kinerja, kan?