PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Kecepatan Pemotongan Postgresql

Ini telah muncul beberapa kali baru-baru ini, baik di SO maupun di milis PostgreSQL.

TL;DR untuk dua poin terakhir Anda:

(a) Shared_buffers yang lebih besar mungkin menjadi alasan mengapa TRUNCATE lebih lambat di server CI. Konfigurasi fsync yang berbeda atau penggunaan media rotasi alih-alih SSD juga bisa menjadi penyebabnya.

(b) TRUNCATE memiliki biaya tetap, tetapi tidak harus lebih lambat dari DELETE , ditambah itu bekerja lebih banyak. Simak penjelasan detailnya berikut ini.

PERBARUI: Diskusi signifikan tentang kinerja pgsql muncul dari posting ini. Lihat utas ini.

PEMBARUAN 2: Perbaikan telah ditambahkan ke 9.2beta3 yang akan membantu dengan ini, lihat posting ini.

Penjelasan mendetail tentang TRUNCATE vs DELETE FROM :

Meskipun bukan ahli dalam topik tersebut, pemahaman saya adalah bahwa TRUNCATE memiliki biaya per tabel yang hampir tetap, sedangkan DELETE setidaknya O(n) untuk n baris; lebih buruk jika ada kunci asing yang merujuk ke tabel yang dihapus.

Saya selalu berasumsi bahwa biaya tetap dari TRUNCATE lebih rendah dari biaya DELETE di meja yang hampir kosong, tapi ini tidak benar sama sekali.

TRUNCATE table; melakukan lebih dari DELETE FROM table;

Status database setelah TRUNCATE table hampir sama seperti jika Anda menjalankan:

  • DELETE FROM table;
  • VACCUUM (FULL, ANALYZE) table; (9.0+ saja, lihat catatan kaki)

... meskipun tentu saja TRUNCATE tidak benar-benar mencapai efeknya dengan DELETE dan VACUUM .

Intinya DELETE dan TRUNCATE lakukan hal yang berbeda, jadi Anda tidak hanya membandingkan dua perintah dengan hasil yang sama.

A DELETE FROM table; memungkinkan baris mati dan mengasapi tetap ada, memungkinkan indeks membawa entri mati, tidak memperbarui statistik tabel yang digunakan oleh perencana kueri, dll.

Sebuah TRUNCATE memberi Anda tabel dan indeks yang benar-benar baru seolah-olah hanya CREATE ed. Ini seperti Anda menghapus semua catatan, mengindeks ulang tabel dan melakukan VACUUM FULL .

Jika Anda tidak peduli jika ada sisa makanan di tabel karena Anda akan pergi dan mengisinya kembali, Anda mungkin lebih baik menggunakan DELETE FROM table; .

Karena Anda tidak menjalankan VACUUM Anda akan menemukan bahwa baris mati dan entri indeks terakumulasi sebagai mengasapi yang harus dipindai kemudian diabaikan; ini memperlambat semua pertanyaan Anda. Jika pengujian Anda tidak benar-benar membuat dan menghapus banyak data yang mungkin tidak Anda perhatikan atau pedulikan, dan Anda selalu dapat melakukan VACUUM atau dua setengah jalan melalui uji coba Anda jika Anda melakukannya. Lebih baik, biarkan pengaturan autovacuum yang agresif memastikan bahwa autovacuum melakukannya untuk Anda di latar belakang.

Anda masih dapat TRUNCATE semua tabel Anda setelah whole test suite berjalan untuk memastikan tidak ada efek yang menumpuk di banyak proses. Pada 9.0 dan yang lebih baru, VACUUM (FULL, ANALYZE) table; global di atas meja setidaknya sama baiknya jika tidak lebih baik, dan itu jauh lebih mudah.

IIRC Pg memiliki beberapa optimasi yang berarti mungkin menyadari ketika transaksi Anda adalah satu-satunya yang dapat melihat tabel dan segera menandai blok sebagai bebas. Dalam pengujian, ketika saya ingin membuat mengasapi, saya harus memiliki lebih dari satu koneksi bersamaan untuk melakukannya. Saya tidak akan mengandalkan ini.

DELETE FROM table; sangat murah untuk meja kecil tanpa referensi f/k

Untuk DELETE semua catatan dari tabel tanpa referensi kunci asing, semua Pg harus melakukan pemindaian tabel berurutan dan mengatur xmax dari tupel yang ditemui. Ini adalah operasi yang sangat murah - pada dasarnya membaca linier dan menulis semi-linear. AFAIK tidak harus menyentuh indeks; mereka terus menunjuk ke tupel mati sampai mereka dibersihkan oleh VACUUM nanti yang juga menandai blok dalam tabel yang hanya berisi tupel mati sebagai bebas.

DELETE hanya menjadi mahal jika ada banyak catatan, jika ada banyak referensi kunci asing yang harus diperiksa, atau jika Anda menghitung tabel VACUUM (FULL, ANALYZE) table; diperlukan untuk mencocokkan TRUNCATE 's dalam biaya DELETE . Anda .

Dalam pengujian saya di sini, tabel DELETE FROM table; biasanya 4x lebih cepat dari TRUNCATE pada 0.5ms vs 2ms. Itu adalah DB pengujian pada SSD, berjalan dengan fsync=off karena saya tidak peduli jika saya kehilangan semua data ini. Tentu saja, DELETE FROM table; tidak melakukan semua pekerjaan yang sama, dan jika saya menindaklanjuti dengan tabel VACUUM (FULL, ANALYZE) table; itu jauh lebih mahal 21ms, jadi DELETE hanya sebuah kemenangan jika saya tidak benar-benar membutuhkan meja yang murni.

TRUNCATE table; melakukan lebih banyak pekerjaan dengan biaya tetap dan tata graha daripada DELETE

Sebaliknya, sebuah TRUNCATE harus melakukan banyak pekerjaan. Itu harus mengalokasikan file baru untuk tabel, tabel TOAST-nya jika ada, dan setiap indeks yang dimiliki tabel. Header harus ditulis ke dalam file-file itu dan katalog sistem mungkin perlu diperbarui juga (tidak yakin tentang hal itu, belum diperiksa). Itu kemudian harus mengganti file lama dengan yang baru atau menghapus yang lama, dan harus memastikan sistem file telah mengikuti perubahan dengan operasi sinkronisasi - fsync() atau serupa - yang biasanya mem-flush semua buffer ke disk . Saya tidak yakin apakah sinkronisasi dilewati jika Anda menjalankan dengan opsi (pemakan data) fsync=off .

Baru-baru ini saya mengetahui bahwa TRUNCATE juga harus membersihkan semua buffer PostgreSQL yang terkait dengan tabel lama. Ini bisa memakan banyak waktu dengan shared_buffers yang besar . Saya menduga inilah mengapa ini lebih lambat di server CI Anda.

Saldo

Bagaimanapun, Anda dapat melihat bahwa TRUNCATE tabel yang memiliki tabel TOAST terkait (sebagian besar dilakukan) dan beberapa indeks dapat memakan waktu beberapa saat. Tidak panjang, tapi lebih dari DELETE dari meja yang hampir kosong.

Akibatnya, Anda mungkin lebih baik melakukan DELETE FROM table; .

--

Catatan:pada DB sebelum 9.0, CLUSTER table_id_seq ON table; ANALYZE table; atau VACUUM FULL ANALYZE table; REINDEX table; akan menjadi setara lebih dekat dengan TRUNCATE . VACUUM FULL impl diubah menjadi yang jauh lebih baik di 9.0.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Impor Data Excel ke PostgreSQL 9.3

  2. Ikhtisar Ekstensi Tepercaya di PostgreSQL 13

  3. Cara Mengekstrak Nomor Minggu dari Tanggal di PostgreSQL

  4. cara membuat tabel tanggal gregorian ISO-8601 di postgres

  5. Sepuluh Tips untuk Memasuki Produksi Dengan PostgreSQL