Pembaruan / penyisipan basis data massal dari file CSV

8

Saya menerapkan fitur aplikasi impor data spesifik dari satu database ke yang lain.

Saya memiliki file CSV yang berisi katakanlah 10.000 baris. Baris-baris ini perlu dimasukkan / diperbarui ke dalam basis data.

Mungkin ada kasusnya, di mana beberapa baris mungkin ada dalam database yang berarti mereka perlu diperbarui. Jika tidak ada dalam database, itu harus dimasukkan.

Salah satu solusi yang mungkin adalah bahwa, saya dapat membaca satu per satu baris, memeriksa entri dalam database dan membangun permintaan masukkan / pembaruan yang sesuai. Tetapi proses ini mungkin membutuhkan banyak waktu untuk membuat pembaruan / menyisipkan kueri dan menjalankannya dalam database. Beberapa kali file CSV saya mungkin memiliki jutaan catatan.

Apakah ada cara lain yang lebih cepat untuk mencapai fitur ini?


sumber
Cobalah untuk memprosesnya dalam beberapa bagian atau pembacaan CSV besar sekaligus akan menghasilkan OutOfMemory!
@TheNewIdiot itu tidak akan terjadi jika menggunakan memori yang cukup seperti server yang layak yang akan menghancurkan setidaknya 2 GB ram ke JVM. Ini juga akan tergantung pada jenis data dalam file CSV dan apakah proses akan berjalan dalam satu proses atau di samping yang lain diproses di server.
@Luiggi Mendoza: Saya setuju dengan Anda. Kami memiliki cukup memori untuk memproses file CSV besar dalam produksi.

Jawaban:

7

Ada teknologi bagus yang tersedia di Oracle yang disebut Tabel Eksternal. Dalam skenario Anda, Anda bisa mengakses data teks biasa eksternal Anda menggunakan Tabel Eksternal dari dalam database dan memperbarui data yang ada dalam database dengan pernyataan SQL yang Anda sukai dan digunakan untuk - misalnya INSERT, MERGEdll.

Dalam kebanyakan kasus, menggunakan utilitas yang disediakan Oracle adalah cara terbaik untuk melakukan ETL. Dan karena pertanyaan Anda terdengar seperti pertanyaan administratif, saya sarankan Anda untuk melihat posting saya sebelumnya di DBA Stack Exchange "Perbarui database Oracle dari CSV" .

PEMBARUAN: Pendekatan ini berfungsi cukup baik untuk membaca data eksternal dalam database. Secara umum, Anda menentukan format data eksternal setiap kali Anda perlu memproses file teks biasa yang memiliki format baru. Setelah tabel eksternal dibuat, Anda dapat menanyakannya seperti tabel database nyata. Setiap kali ada data baru untuk diimpor, Anda cukup mengganti file yang mendasarinya dengan cepat tanpa perlu membuat ulang tabel eksternal. Karena tabel eksternal dapat dikenali sebagai tabel database lainnya, Anda dapat menulis pernyataan SQL untuk mengisi tabel database lainnya.

Biaya tambahan untuk menggunakan Tabel Eksternal biasanya lebih rendah dibandingkan dengan teknik lain yang akan Anda terapkan secara manual karena teknologi ini dirancang dengan mempertimbangkan kinerja arsitektur Oracle Database.

Yasir Arsanukaev
sumber
Saya setuju ini adalah salah satu solusi untuk mencapai tujuan saya. Bagaimana pendekatan ini cocok untuk pemrosesan CSV dinamis? Berarti, pengguna aplikasi saya memiliki kesempatan untuk mengunggah banyak file dengan format yang berbeda (dalam hal ini kisah eksternal perlu dibuat dengan cepat). Juga, satu file CSV dapat berisi data yang perlu diisi ke dalam beberapa tabel.
1

Saya pikir Anda harus menggunakan SQL * Loader untuk memuat file CSV ke tabel sementara dan kemudian menggunakan pernyataan MERGE untuk memasukkan data ke dalam tabel kerja.
SQL * Loader akan memberi Anda lebih banyak fleksibilitas daripada tabel eksternal dan jika seseorang menggunakan load path langsung, ia sangat cepat. Dan MERGE akan melakukan apa yang Anda butuhkan - Sisipkan catatan baru dan perbarui yang sudah ada.
Beberapa tautan untuk memulai:
http://docs.oracle.com/cd/B19306_01/server.102/b14215/ldr_concepts.htm
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016 .htm

Mindaugas Riauba
sumber
1
Ketika Anda memuat data ke dalam database menggunakan SQL Loader proses DBWR atau proses SQL Loader menulis buffer ke file data. Ketika Anda selanjutnya memindahkan data yang dimuat ke tabel lain database melakukan I / O lain. Saya tidak berpikir pekerjaan ekstra ini bisa dibenarkan. Omong-omong ketika Tabel Eksternal menggunakan driver ORACLE_LOADER, sintaks untuk menentukan format data input sama dengan yang digunakan oleh utilitas sqlldr karena pada dasarnya mereka adalah teknologi yang sama dan dengan demikian dapat digunakan secara bergantian. Tabel Eksternal dalam skenario ini lebih disukai karena tidak perlu memuat data ke dalam database terlebih dahulu
Yasir Arsanukaev
Seperti biasa jawabannya adalah "itu tergantung" :). Dalam kasus kami, biasanya lebih mudah memuat ke tabel temp dulu dan diproses kemudian. Karena beban jalur langsung tidak menghasilkan ulang sehingga I / O tambahan hampir tidak terlihat di antara operasi lain. Dalam kasus lain tentu saja metode lain akan lebih baik.
Mindaugas Riauba
0

PreparedStatements akan membuat pembuatan memasukkan atau memperbarui kueri sangat cepat. Anda harus memiliki tiga PreparedStatements: Satu untuk disisipkan, satu untuk pembaruan, dan satu untuk memeriksa apakah baris sudah ada dalam tabel. Jika Anda dapat menjaga ID yang sama antara file CSV dan database baru, maka memeriksa untuk melihat apakah ada baris menggunakan bidang primaryID juga harus sangat cepat.

Menggunakan bets insert dapat menawarkan peningkatan kinerja. Ketika Anda melakukan streaming melalui file CSV, Anda kemudian akan memeriksa apakah baris sudah ada di sana dan kemudian melakukan pembaruan atau menambahkan baris ke perintah masukkan batch Anda. Anda harus memeriksa pertanyaan SO ini untuk perbandingan kecepatan kedua pendekatan ini.

Jika impor basis data ini adalah sesuatu yang perlu dilakukan secara teratur dan kinerja adalah masalah menggunakan metode yang saya uraikan di atas, maka Anda dapat mencoba menangani tugas dengan beberapa utas pekerja. Gunakan sebanyak mungkin utas sebagai pengolah pada mesin yang menjalankan kode ini.

  int nThreads = Runtime.getRuntime().availableProcessors();

Setiap utas mendapatkan koneksi DB sendiri dan karena kode Anda berulang melalui file, garis CSV dapat diserahkan ke berbagai utas. Ini jauh lebih rumit, jadi saya hanya akan melakukan ini jika persyaratan kinerja memaksa saya untuk melakukannya.

Komunitas
sumber
Terima kasih untuk balasan Anda. Sekali lagi, ini akan membutuhkan file parsing dan mengisi nilai CSV ke dalam pernyataan yang disiapkan. Dengan pendekatan 'Tabel Eksternal', saya melihat parsing file dapat dipindahkan ke sisi Database di mana aplikasi tidak perlu peduli tentang hal itu. Juga, saya menggunakan JPA dengan Hibernate di aplikasi saya. Saya mencari opsi yang dapat merupakan kombinasi dari JPA / Hibernate / Oracle yang tidak memfasilitasi penguraian file, kinerja yang baik, dapat dikelola dan fleksibel.