Saya mencoba mem-port beberapa kueri MySQL lama ke PostgreSQL, tetapi saya mengalami masalah dengan yang ini:
DELETE FROM logtable ORDER BY timestamp LIMIT 10;
PostgreSQL tidak mengizinkan pengurutan atau batasan dalam sintaks hapus, dan tabel tidak memiliki kunci utama sehingga saya tidak dapat menggunakan subkueri. Selain itu, saya ingin mempertahankan perilaku di mana kueri menghapus persis nomor atau catatan yang diberikan - misalnya, jika tabel berisi 30 baris tetapi semuanya memiliki stempel waktu yang sama, saya masih ingin menghapus 10, meskipun tidak masalah yang 10.
Begitu; bagaimana cara menghapus sejumlah baris dengan pengurutan di PostgreSQL?
Edit: Tidak ada kunci utama berarti tidak ada log_id
kolom atau sejenisnya. Ah, nikmatnya sistem warisan!
sql
postgresql
Apa
sumber
sumber
alter table foo add column id serial primary key
.Jawaban:
Anda dapat mencoba menggunakan
ctid
:The
ctid
adalah:Ada juga
oid
tetapi itu hanya ada jika Anda secara khusus memintanya saat Anda membuat tabel.sumber
VACUUM FULL
atau autovacuum menyebabkan masalah jika mereka mengubahctid
nilai dalam tabel saat kueri sedang berjalan?ctid
dokumentasinya adalahctid
cukup stabil untuk membuat DELETE ini berfungsi dengan baik tetapi tidak cukup stabil untuk, misalnya, diletakkan di tabel lain sebagai ghetto-FK. Agaknya Anda tidak MEMPERBARUIlogtable
sehingga Anda tidak perlu khawatir tentang perubahanctid
itu danVACUUM FULL
mengunci tabel ( postgresql.org/docs/current/static/routine-vacuuming.html ) sehingga Anda tidak perlu khawatir tentang cara lain yangctid
bisa berubah. PostgreSQL-Fu @ araqnid cukup kuat dan dokumen setuju dengannya untuk boot.Dokumen Postgres merekomendasikan untuk menggunakan array daripada IN dan subquery. Ini akan bekerja lebih cepat
Ini dan beberapa trik lainnya dapat ditemukan di sini
sumber
any (array( ... ));
lebih cepat dariin ( ... )
itu terdengar seperti bug dalam pengoptimal kueri - ia harus dapat melihat transformasi itu dan melakukan hal yang sama dengan datanya sendiri.IN
padaUPDATE
(yang mungkin menjadi perbedaannya).sumber
Dengan asumsi Anda ingin menghapus SETIAP 10 catatan (tanpa pemesanan) Anda dapat melakukan ini:
Untuk kasus penggunaan saya, menghapus 10 juta data, ternyata ini lebih cepat.
sumber
Anda bisa menulis prosedur yang mengulang penghapusan untuk baris individu, prosedur dapat mengambil parameter untuk menentukan jumlah item yang ingin Anda hapus. Tapi itu sedikit berlebihan dibandingkan dengan MySQL.
sumber
Jika Anda tidak memiliki kunci utama, Anda dapat menggunakan sintaks array Where IN dengan kunci komposit.
Ini berhasil untuk saya.
sumber