Saya perlu secara program memasukkan 10 dari jutaan catatan ke dalam database postgres. Saat ini saya sedang mengeksekusi 1000 pernyataan memasukkan dalam satu "permintaan".
Apakah ada cara yang lebih baik untuk melakukan ini, beberapa pernyataan penyisipan massal yang tidak saya ketahui?
Ada alternatif untuk menggunakan COPY, yang merupakan sintaks nilai multirow yang didukung Postgres. Dari dokumentasi :
Kode di atas menyisipkan dua baris, tetapi Anda dapat memperpanjangnya secara sewenang-wenang, sampai Anda menekan jumlah maksimum token pernyataan yang disiapkan (mungkin $ 999, tapi saya tidak 100% yakin tentang itu). Terkadang seseorang tidak dapat menggunakan COPY, dan ini adalah pengganti yang layak untuk situasi tersebut.
sumber
Salah satu cara untuk mempercepatnya adalah dengan secara eksplisit melakukan beberapa sisipan atau salinan dalam suatu transaksi (katakanlah 1000). Perilaku default Postgres adalah melakukan setelah setiap pernyataan, jadi dengan mengelompokkan komit, Anda dapat menghindari beberapa overhead. Seperti panduan dalam jawaban Daniel mengatakan, Anda mungkin harus menonaktifkan autocommit agar ini berfungsi. Perhatikan juga komentar di bagian bawah yang menunjukkan peningkatan ukuran wal_buffers menjadi 16 MB juga dapat membantu.
sumber
UNNEST
fungsi dengan array dapat digunakan bersama dengan sintaks VALUES multirow. Saya pikir metode ini lebih lambat daripada menggunakanCOPY
tetapi berguna bagi saya dalam bekerja dengan psycopg dan python (pythonlist
dilewatkancursor.execute
menjadi pgARRAY
):tanpa
VALUES
menggunakan subselect dengan pemeriksaan keberadaan tambahan:sintaksis yang sama untuk pembaruan massal:
sumber
Anda dapat menggunakan
COPY table TO ... WITH BINARY
yang " agak lebih cepat dari format teks dan CSV ." Hanya lakukan ini jika Anda memiliki jutaan baris untuk disisipkan, dan jika Anda merasa nyaman dengan data biner.Berikut adalah contoh resep dalam Python, menggunakan psycopg2 dengan input biner .
sumber
Sebagian besar tergantung pada aktivitas (lainnya) dalam database. Operasi seperti ini secara efektif membekukan seluruh basis data untuk sesi lain. Pertimbangan lain adalah model data dan adanya kendala, pemicu, dll.
Pendekatan pertama saya adalah selalu: membuat tabel (temp) dengan struktur yang mirip dengan tabel target (buat tabel tmp AS pilih * dari target di mana 1 = 0), dan mulai dengan membaca file ke dalam tabel temp. Lalu saya periksa apa yang bisa diperiksa: duplikat, kunci yang sudah ada di target, dll.
Lalu saya hanya melakukan "jangan masukkan ke target pilih * dari tmp" atau serupa.
Jika ini gagal, atau terlalu lama, saya batalkan dan pertimbangkan metode lain (sementara menjatuhkan indeks / kendala, dll)
sumber
Saya menerapkan pemuat data Postgresq yang sangat cepat dengan metode libpq asli. Coba paket saya https://www.nuget.org/packages/NpgsqlBulkCopy/
sumber
Saya baru saja mengalami masalah ini dan akan merekomendasikan csvsql ( rilis ) untuk impor massal ke Postgres. Untuk melakukan penyisipan massal Anda cukup
createdb
dan kemudian menggunakancsvsql
, yang menghubungkan ke database Anda dan membuat tabel individual untuk seluruh folder CSV.sumber
File eksternal adalah data massal terbaik dan tipikal
Istilah "data massal" terkait dengan "banyak data", jadi wajar untuk menggunakan data mentah asli , tanpa perlu mengubahnya menjadi SQL. File data mentah yang umum untuk "sisipan massal" adalah format CSV dan JSON .
Sisipkan massal dengan beberapa transformasi
Dalam aplikasi ETL dan proses menelan, kita perlu mengubah data sebelum memasukkannya. Tabel sementara mengkonsumsi (banyak) ruang disk, dan itu bukan cara yang lebih cepat untuk melakukannya. The PostgreSQL asing-data yang wrapper (FDW) adalah pilihan terbaik.
Contoh CSV . Misalkan
tablename (x, y, z)
pada SQL dan file CSV sukaAnda dapat menggunakan SQL klasik
COPY
untuk memuat ( seperti data asli) ke dalamtmp_tablename
, mereka memasukkan data yang disaring ketablename
... Tapi, untuk menghindari konsumsi disk, yang terbaik adalah dengan langsung dicerna olehAnda perlu menyiapkan basis data untuk PLRT Asing, dan sebaliknya statis
tmp_tablename_fdw
Anda bisa menggunakan fungsi yang menghasilkannya :Contoh JSON . Seperangkat dua file,
myRawData1.json
danRanger_Policies2.json
dapat dicerna dengan:di mana fungsi jsonb_read_files () membaca semua file folder, ditentukan oleh mask:
Kurangnya streaming gzip
Metode yang paling sering untuk "konsumsi file" (terutama di Big Data) adalah mempertahankan file asli pada format gzip dan mentransfernya dengan algoritma streaming , apa pun yang dapat berjalan cepat dan tanpa konsumsi diska di pipa unix:
Jadi ideal (masa depan) adalah opsi server untuk format
.csv.gz
.sumber