Apa yang khusus dilakukan oleh OracleBulkCopy, dan bagaimana saya dapat mengoptimalkan kinerjanya?

14

Untuk meringkas spesifikasinya: Kita perlu memasukkan sekitar 5 juta baris ke dalam database vendor (Oracle). Semuanya berjalan baik untuk kumpulan 500k baris menggunakan OracleBulkCopy(ODP.NET), tetapi ketika kami mencoba untuk skala hingga 5M, kinerja mulai melambat ke perayapan setelah menyentuh tanda 1M, semakin lambat karena semakin banyak baris dimuat, dan akhirnya habis setelah 3 jam atau lebih.

Saya menduga itu terkait dengan kunci utama di atas meja, tapi aku sudah trawl forum Oracle dan Stack Overflow untuk informasi dan banyak apa yang saya baca bertentangan itu (juga, banyak posting tampaknya bertentangan satu sama lain ) . Saya berharap seseorang dapat meluruskan beberapa pertanyaan terkait erat tentang proses:

  1. Apakah OracleBulkCopykelas menggunakan pemuatan jalur konvensional atau langsung? Apakah ada cara saya dapat mengkonfirmasi ini, dengan satu atau lain cara?

  2. Dengan asumsi itu tidak digunakan langsung jalan memuat: Apakah benar bahwa Oracle secara otomatis mengatur semua indeks untuk dapat digunakan selama beban dan menempatkan mereka kembali online sesudahnya? Saya telah membaca beberapa pernyataan untuk efek ini tetapi sekali lagi, tidak dapat mengonfirmasinya.

  3. Jika # 2 benar, maka haruskah membuat perbedaan indeks apa yang ada di meja sebelum saya memulai operasi salinan massal? Jika demikian, mengapa?

  4. Terkait dengan # 3, apakah ada perbedaan praktis, secara umum, antara pemuatan massal dengan indeks yang tidak dapat digunakan vs benar-benar menjatuhkan indeks sebelum memuat dan membuatnya kembali sesudahnya?

  5. Jika # 2 tidak benar, atau jika ada beberapa peringatan yang saya tidak mengerti, maka apakah ada bedanya untuk secara eksplisit membuat indeks tidak dapat digunakan sebelum memuat massal, dan kemudian secara eksplisit membangunnya kembali setelah itu?

  6. Apakah ada hal lain, selain pembuatan indeks, yang dapat menyebabkan operasi salinan massal tumbuh semakin lambat karena semakin banyak catatan ditambahkan? (Mungkin ada hubungannya dengan logging, walaupun saya berharap operasi massal tidak dicatat?)

  7. Jika benar-benar tidak ada cara lain untuk meningkatkan kinerja selain menjatuhkan PK / indeks terlebih dahulu, langkah-langkah apa yang dapat saya ambil untuk memastikan bahwa indeks tidak sepenuhnya hilang, yaitu jika koneksi ke database terputus di tengah proses?

Aaronaught
sumber
Catatan: Data yang disalin sudah dalam urutan diurutkan menurut PK, yang merupakan satu-satunya indeks di atas meja.
Aaronaught
Apakah Anda menggunakan DataReader untuk membaca data dari sumbernya?
bernd_k
@bernd_k: Tidak, memuat seluruhnya dari memori. Jelas bukan sumber itulah masalahnya.
Aaronaught

Jawaban:

13

Beberapa hari lagi membaca dan bereksperimen dan saya dapat (kebanyakan) menjawab banyak dari ini:

  1. Saya menemukan ini terkubur dalam dokumentasi ODP.NET (ironisnya tidak ada dalam OracleBulkCopydokumen):

    Fitur Salinan Massal ODP.NET menggunakan pendekatan load path langsung, yang mirip dengan, tetapi tidak sama dengan Oracle SQL * Loader. Menggunakan beban jalur langsung lebih cepat daripada memuat konvensional (menggunakan INSERTpernyataan SQL konvensional ).

    Jadi tampak bahwa itu tidak menggunakan jalur langsung.

  2. Ini saya dapat memverifikasi dengan melakukan operasi salinan massal besar dan mendapatkan properti indeks dari Pengembang SQL. Indeks memang muncul UNUSABLEsaat salinan massal sedang berlangsung. Namun , saya juga menemukan bahwa OracleBulkCopy.WriteToServerakan menolak untuk berjalan jika indeks dimulai dalam UNUSABLEkeadaan, jadi jelas ada lebih banyak yang terjadi di sini, karena jika itu sederhana seperti menonaktifkan dan membangun kembali indeks maka tidak seharusnya peduli dengan keadaan awal.

  3. Itu membuat perbedaan khusus jika indeks juga merupakan kendala . Temukan permata kecil ini di dokumentasi yang ditautkan di atas:

    Kendala yang Diaktifkan
    Selama salinan massal Oracle, batasan-batasan berikut secara otomatis diaktifkan secara default:

    • NOT NULL
    • UNIQUE
    • PRIMARY KEY (kendala unik pada kolom bukan nol)

    NOT NULLkendala diperiksa pada waktu pembuatan array kolom. Setiap baris yang melanggar NOT NULLbatasan ditolak.

    UNIQUEkendala diverifikasi ketika indeks dibangun kembali pada akhir beban. Indeks dibiarkan dalam status Indeks Tidak Dapat Digunakan jika melanggar UNIQUEbatasan.

    Dokumentasi sedikit kabur tentang apa yang terjadi selama pemuatan, terutama dengan kunci primer, tetapi satu hal yang pasti - berperilaku berbeda dengan kunci primer vs tanpa satu. Karena dengan OracleBulkCopysenang hati akan memungkinkan Anda melanggar batasan indeks (dan menusuk indeks ke dalam UNUSABLEkeadaan ketika selesai), firasat saya adalah bahwa itu membangun indeks PK selama salinan massal tetapi tidak memvalidasinya sampai sesudahnya.

  4. Saya tidak yakin apakah perbedaan yang diamati adalah dalam Oracle itu sendiri atau hanya kekhasan dari OracleBulkCopy. Juri masih keluar untuk yang satu ini.

  5. OracleBulkCopyakan melempar pengecualian jika indeks awalnya di UNUSABLEnegara bagian, jadi itu benar-benar titik diperdebatkan.

  6. Jika ada yang faktor-faktor lain, indeks (dan indeks terutama PK) masih yang paling penting, seperti yang saya tahu oleh:

  7. Membuat tabel sementara global dengan skema yang sama (menggunakan CREATE AS), kemudian menyalin massal ke tabel sementara, dan akhirnya melakukan yang lama biasa INSERTdari tabel temp ke dalam tabel nyata. Karena tabel temp tidak memiliki indeks, salinan massal terjadi sangat cepat, dan final INSERTjuga cepat karena data sudah ada dalam tabel (saya belum mencoba petunjuk tambahan, karena salinan table-to-table 5M baris baris sudah memakan waktu kurang dari 1 menit).

    Saya belum yakin tentang konsekuensi potensial dari (ab) menggunakan ruang tabel sementara dengan cara ini, tapi sejauh ini tidak memberi saya masalah, dan itu jauh lebih aman daripada alternatif dengan cara mencegah korupsi pada kedua baris atau indeks.

    Keberhasilan ini juga cukup jelas menunjukkan bahwa indeks PK adalah masalahnya, karena itulah satu-satunya perbedaan praktis antara tabel temp dan tabel permanen - keduanya dimulai dengan nol baris selama pengujian kinerja.

Kesimpulan: Jangan repot-repot mencoba menyalin secara massal lebih dari sekitar 100 ribu baris ke tabel Oracle yang diindeks menggunakan ODP.NET. Baik drop indeks (jika Anda tidak benar-benar membutuhkannya) atau "preload" data ke dalam yang berbeda (non-diindeks) tabel.

Aaronaught
sumber
Saya tidak yakin tentang pengecekan batasan kunci primer. Saya senang memasukkan data yang sama secara massal ke tabel Oracle 2 kali dan Select * menunjukkan 2 baris yang digandakan. Dalam keadaan itu Hapus tidak mungkin, tetapi tabel truncate membantu untuk kembali ke kondisi bersih.
bernd_k
@bernd_k: Deletetidak mungkin karena indeksnya UNUSABLE. Itu adalah hasil dari pengecekan kendala yang terjadi pada akhir salinan massal.
Aaronaught
Saya memiliki skript PowerShell yang sedang berjalan, memanggil bulkcopy ke dalam database Oracle dari pembaca data SQL Server, semua tabel target dengan Kunci utama dan saya tidak punya masalah dengan tabel dengan baris hingga 205278. Tapi saya sangat berhati-hati untuk mengisi tabel master terlebih dahulu sebelum mengisi tabel detail. Saya tidak menghapus salah satu indeks lain di atas meja dan saya tidak punya masalah ketika tabel awalnya kosong.
bernd_k
@bernd_k: Ya, saya juga tidak punya banyak masalah di volume itu (lihat paragraf terakhir saya). Justru ketika Anda mencapai jutaan yang menjadi mengerikan. Juga mungkin ada perbedaan jika Anda mengosongkan tabel beberapa saat setelah setiap salinan massal (yang ini tidak dikosongkan, akan ditambahkan ke, dan Anda tahu bagaimana indeks menjadi lebih lambat karena mereka semakin besar).
Aaronaught
Mungkin ini membantu ketika Anda melakukanalter session set skip_unusable_indexes = true;
Wernfried Domscheit
1

Berikut ini adalah artikel dari Oracle yang menjelaskan kapan akan bermanfaat menggunakan insert massal atau ketika tidak. Juga, memiliki wawasan tentang apa yang terjadi di tingkat basis data.

http://docs.oracle.com/cd/B28359_01/server.111/b28319/ldr_modes.htm

SmartCoder
sumber
3
Tautan cenderung membusuk; Anda mungkin ingin memasukkan informasi yang relevan dari tautan dalam jawaban Anda.
mustaccio