Oracle 11g: peningkatan kinerja sisipan

8

Saya memiliki tabel 500 juta baris (dan terus bertambah)

Saya melakukan yang berikut ini untuk meningkatkan kinerja sisipan:

Di sisi basis data:

  • menjatuhkan semua indeks dan batasan
  • logging dinonaktifkan

Di sisi aplikasi:

  • beralih dari entitas yang dikelola JPA ke kueri insert asli, menambahkan LAMPIRAN petunjuk Oracle ke kueri
  • mencoba komit dalam batch per 1k / 2k / 3k baris
  • mencoba menulis secara paralel (beberapa utas, jumlah utas = ke jumlah inti pada server) ke satu tabel

Ini memberi saya sekitar 300 baris per detik

Selain itu dicoba:

  • tulis secara paralel dalam batch ke beberapa tabel (untuk mengelompokkan kemudian mengembalikan hasil menggunakan UNION)

Ini memberi saya sekitar 1rb baris per detik, tetapi di atas meja kosong. Tetapi ketika saya mengisi tabel dengan data dummy (masing-masing 200 juta), kecepatan insert turun menjadi 250 - 300 per detik.

Adakah yang bisa menyarankan apa lagi yang bisa saya lakukan untuk mempercepat insert? Pada dasarnya saya ingin mengerti apa itu (apa yang bisa) bottleneck dulu.

UPD: Tabel dipartisi berdasarkan tanggal penyisipan, tabel memiliki sekitar 60 kolom - sebagian besar kolom adalah VARCHAR2 (2000 BYTE)

terpaut
sumber
Anda tahu bahwa dengan logging dinonaktifkan, kegagalan media antara beban dan penyelesaian cadangan berikutnya pertama akan meninggalkan seluruh tabel, atau bagian dari itu dalam kasus insert jalur langsung, tidak dapat dipulihkan, kan?
David Aldridge
1
(1) Hanya satu sesi yang dapat menambahkan pada satu waktu di atas meja. (2) /*+APPEND*/petunjuk tersebut diabaikan pada sisipan baris tunggal (jika Anda tidak perlu INSERT INTO ... SELECTrepot menambahkan). (3) Anda harus menyiapkan contoh SQL * Loader dengan direct=truemenetapkan dasar seperti yang disarankan oleh @parsifal.
Vincent Malgrat
Apakah Anda menjalankan perangkat keras nyata atau mesin virtual? Jika VM, apakah file disk jarang (yaitu: tidak sepenuhnya dialokasikan sebelumnya)? Juga, silakan edit pertanyaan Anda dengan output dari laporan statspack atau awr (bagian menunggu atas).
Philᵀᴹ
Masalah / kebutuhan apa yang dipartisi dengan memenuhi / memenuhi tanggal partisi?
Brian
Apa sumber data Anda untuk tabel ini? Apakah ini beban batch dari file ASCII atau apakah itu dibuat pengguna atau sesuatu yang lain. Harap spesifik.
RMAN Express

Jawaban:

5

Baru saja melihat pembaruan, tabel 60-col dengan sebagian besar bidang VARCHAR (2k) - yaitu (berpotensi) tabel monster.

Hal pertama yang pertama ...

Anda harus memahami hambatan Anda PERTAMA. Di sisi aplikasi, kembalilah ke solusi batch-threaded single-threaded Anda (1/2 / 3k sekaligus) dan mulai jalankan dan login ke mesin DB dan jalankan 'top' - lihat berapa banyak waktu proses DB mengambil DAN berapa banyak (jika ada) wa% waktu mesin ditampilkan.

Jika top menunjukkan kapan saja wa%, itu berarti DB Anda terikat I / O dan Anda mungkin perlu mempertimbangkan beberapa mesin DB (pecahan) atau mempertimbangkan melempar SSD pada mesin host.

Itu dia; penelitian Anda berhenti di sini. Tidak masalah berapa banyak CPU yang diambil oleh DB atau seberapa jenuh klien aplikasi Anda; jika Anda menekan masalah latensi I / O pada host DB, itu secepat itu akan PERNAH pergi untuk Anda.

TIP Jika perubahan perangkat keras keluar dari pertanyaan, tergantung pada sistem file yang Anda jalankan (Linux) Anda dapat mencoba menonaktifkan logging atau penulisan metadata untuk DB untuk sedikit meningkatkan kinerja pada tingkat sistem file. Anda dapat melakukan hal serupa pada NTFS, tetapi ini hanya akan memberi Anda sedikit dorongan. Ini tidak akan 2x.

Sekarang, yang kedua ...

Katakanlah Anda memiliki waktu tunggu sebentar lagi tetapi CPU Anda dipatok sepenuhnya oleh proses DB. Satu-satunya pilihan Anda sekarang adalah untuk memperkenalkan lebih banyak mesin DB (pecahan) dan membagi pekerjaan.

Sekali lagi, Anda sudah selesai dengan penelitian Anda jika ini masalahnya. Tidak ada yang dapat Anda lakukan untuk mengubah CPU agar lebih cepat.

Terakhir, hal ketiga ... ketiga ...

Katakanlah DB tidak melakukan banyak hal. Lalu, buka mesin klien yang menjalankan batch insert dan periksa beban CPU - apakah dipatok? Jika demikian, jalankan beberapa mesin lagi melakukan insert batch yang sama persis dan lihat apakah Anda bisa mendapatkan jalan linier.

Jika CPU tidak dipatok, jalankan beberapa utas lagi di mesin yang sama hingga dipatok dan lihat bagaimana skala DB.

Saya pikir Anda mungkin sudah mencobanya, jadi tebakan saya adalah bahwa host klien Anda sudah dipatok (dan lebih banyak utas tidak akan membuat perbedaan) atau DB sudah mencapai batasnya dan tidak dapat skala lebih jauh.

Tambahan

Melakukan penyisipan mentah pada tabel yang tidak diindeks yang tidak memiliki sampah di dalamnya pada dasarnya adalah operasi APPEND yang harus berjalan secepat disk dapat menangani penulisan.

Membuat lebih banyak tabel pada mesin host yang sama tidak akan membantu, jika apa pun itu akan meningkatkan upaya disk Anda (untuk sampai ke tabel lain pada disk untuk ditambahkan) dan akan memperlambat segalanya.

Sangat penting untuk mencari tahu kemacetan itu terlebih dahulu, lalu kita bisa mengoptimalkannya.

Semoga itu bisa membantu! Buat kami tetap diposting.

Riyad Kalla
sumber
2
Mengapa Anda belum menyebutkan awr atau statspack?
Philᵀᴹ
Dengan petunjuk tambahan, semua kecuali salah satu utas tersebut akan menganggur karena penguncian eksklusif. Saya tidak berpikir kode ini berada pada tahap efisiensi di mana penyetelan tingkat sistem diperlukan - metodologi itu sendiri yang cacat.
David Aldridge
Berpikir lebih jauh, saya percaya pendekatan Anda memiliki kelemahan mendasar. Jika Viktors mencoba metode penyisipan single-threaded dan memiliki waktu tunggu I / O, itu bisa disebabkan oleh metode penyisipan yang tidak efisien dan komitmen berlebihan (menunggu file log sync). Langkah paling penting adalah memahami mekanisme Oracle dan memilih yang paling tepat dulu?
David Aldridge
@DavidAldridge Viktors mengklarifikasi bahwa ia telah menonaktifkan logging (dan indeks) mengingat bahwa, saya berasumsi tidak ada lagi yang dilakukan DB selain mengalirkan data yang dimasukkan langsung ke file tabel, itulah mengapa saya membuatnya melompat langsung untuk melihat Aku menunggu. Mungkin ada lebih banyak hal yang dilakukan Oracle yang harus / dapat dinonaktifkan - itu adalah titik investigasi yang baik, saya tidak tahu kedalaman Oracle cukup baik untuk membantu di sana sayangnya.
Riyad Kalla
4

Menjalankan penyisipan jalur langsung dengan petunjuk tambahan menyebabkan kunci eksklusif akan diambil terhadap seluruh tabel, sehingga memiliki beberapa utas yang melakukan penyisipan tidak akan membantu. Anda perlu secara eksplisit mengatasi partisi yang berbeda dengan setiap sisipan ...

insert /*+ append */ into my_table partition (partition_name_1) ...

... untuk mendapatkan kunci eksklusif tingkat partisi. Anda tidak akan dapat melakukannya dengan tabel dipartisi pada tanggal penyisipan, kemungkinan besar, tetapi Anda bisa menggunakan partisi gabungan (bukan sub-partisi) untuk mendapatkan beberapa partisi per rentang unik tanggal memasukkan.

Jangan komit di tengah-tengah sisipan, hanya di akhir.

David Aldridge
sumber
Apakah saya perlu menyebutkan nama partisi dalam kueri secara eksplisit? Saya memiliki kolom, semacam jenis acara. Saya akan mencoba untuk mempartisi berdasarkan kelompok acara dan membuat sehingga setiap utas memasukkan batch baris hanya dari jenis tertentu
terpaut
Untuk menghindari kunci eksklusif tingkat meja, ya Anda lakukan.
David Aldridge
Petunjuk LAMPIRAN harus diabaikan oleh Oracle untuk sisipan satu baris. Deskripsi proses oleh OP tampaknya menyiratkan memasukkan batch tunggal. Saya tidak yakin bagaimana mereka diperlakukan. Saya kira tidak ada LAMPIRAN tetapi perlu beberapa pengujian.
Vincent Malgrat
Hmmm, tidak menganggap itu - bahkan lebih buruk, jika demikian.
David Aldridge
Apakah layak untuk mencoba sisipan multi-baris dengan petunjuk LAMPIRAN? Lalu berapa banyak entri per insert multi-baris yang harus saya kirim?
terpaut