Sejauh yang saya tahu Anda dapat mengoptimalkan insert massal dengan cara yang sangat mirip bahwa Anda akan mengoptimalkan insert reguler. Biasanya, rencana kueri untuk penyisipan sederhana tidak terlalu informatif sehingga jangan khawatir tentang tidak memiliki rencana. Saya akan membahas beberapa cara untuk mengoptimalkan sisipan tetapi kebanyakan dari mereka mungkin tidak berlaku untuk sisipan yang Anda tentukan dalam pertanyaan. Namun, mereka bisa membantu jika di masa depan Anda perlu memuat data dalam jumlah yang lebih besar.
1. Masukkan data dalam urutan kunci pengelompokan
SQL Server akan sering mengurutkan data sebelum memasukkannya ke dalam tabel dengan indeks berkerumun. Untuk beberapa tabel dan aplikasi Anda dapat meningkatkan kinerja dengan menyortir data dalam file datar dan membiarkan SQL Server tahu bahwa data diurutkan melalui ORDER
argumen BULK INSERT
:
ORDER ({kolom [ASC | DESC]} [, ... n])
Menentukan bagaimana data dalam file data diurutkan. Kinerja impor massal ditingkatkan jika data yang diimpor disortir menurut indeks berkerumun di tabel, jika ada.
Karena Anda menggunakan IDENTITY
kolom sebagai kunci berkerumun, Anda tidak perlu khawatir tentang ini.
2. Gunakan TABLOCK
jika memungkinkan
Jika Anda dijamin hanya memiliki satu sesi memasukkan data ke tabel Anda, Anda dapat menentukan TABLOCK
argumen untuk BULK INSERT
. Ini dapat mengurangi pertikaian kunci dan dapat menyebabkan minimal logging di beberapa skenario. Namun, Anda memasukkan ke dalam tabel dengan indeks berkerumun yang sudah berisi data sehingga Anda tidak akan mendapatkan penebangan minimal tanpa jejak bendera 610 yang disebutkan kemudian dalam jawaban ini.
Jika TABLOCK
tidak memungkinkan, karena Anda tidak dapat mengubah kode , tidak semua harapan hilang. Pertimbangkan menggunakan sp_table_option
:
EXEC [sys].[sp_tableoption]
@TableNamePattern = N'dbo.BulkLoadTable' ,
@OptionName = 'table lock on bulk load' ,
@OptionValue = 'ON'
Pilihan lain adalah mengaktifkan jejak flag 715 .
3. Gunakan ukuran batch yang sesuai
Terkadang Anda dapat menyetel sisipan dengan mengubah ukuran bets.
ROWS_PER_BATCH = rows_per_batch
Menunjukkan perkiraan jumlah baris data dalam file data.
Secara default, semua data dalam file data dikirim ke server sebagai satu transaksi, dan jumlah baris dalam batch tidak diketahui oleh optimizer kueri. Jika Anda menentukan ROWS_PER_BATCH (dengan nilai> 0) server menggunakan nilai ini untuk mengoptimalkan operasi impor massal. Nilai yang ditentukan untuk ROWS_PER_BATCH harus kira-kira sama dengan jumlah baris aktual. Untuk informasi tentang pertimbangan kinerja, lihat "Keterangan," nanti dalam topik ini.
Berikut ini kutipan dari artikel selanjutnya:
Jika jumlah halaman yang akan disiram dalam satu batch melebihi ambang internal, pemindaian penuh dari kumpulan buffer mungkin terjadi untuk mengidentifikasi halaman mana yang akan disiram ketika batch melakukan. Pemindaian lengkap ini dapat merusak kinerja impor massal. Kasus kemungkinan melebihi ambang internal terjadi ketika kumpulan buffer besar dikombinasikan dengan subsistem I / O yang lambat. Untuk menghindari buffer overflows pada mesin besar, jangan gunakan petunjuk TABLOCK (yang akan menghapus optimasi massal) atau menggunakan ukuran batch yang lebih kecil (yang menjaga optimasi bulk).
Karena komputer berbeda-beda, kami sarankan Anda menguji berbagai ukuran bets dengan beban data Anda untuk mengetahui mana yang paling cocok untuk Anda.
Secara pribadi saya hanya akan memasukkan semua 695 baris dalam satu batch. Tuning ukuran batch dapat membuat perbedaan besar saat memasukkan banyak data.
4. Pastikan Anda membutuhkan IDENTITY
kolom
Saya tidak tahu apa-apa tentang model atau persyaratan data Anda, tetapi jangan jatuh ke dalam perangkap menambahkan IDENTITY
kolom ke setiap tabel. Aaron Bertrand memiliki artikel tentang kebiasaan buruk ini untuk ditendang: meletakkan kolom IDENTITAS di setiap meja . Untuk lebih jelasnya, saya tidak mengatakan bahwa Anda harus menghapus IDENTITY
kolom dari tabel ini. Namun, jika Anda menentukan bahwa IDENTITY
kolom tidak diperlukan dan menghapusnya yang dapat meningkatkan kinerja penyisipan.
5. Nonaktifkan indeks atau batasan
Jika Anda memuat sejumlah besar data ke dalam tabel dibandingkan dengan apa yang sudah Anda miliki maka mungkin lebih cepat untuk menonaktifkan indeks atau kendala sebelum memuat dan untuk mengaktifkannya setelah memuat. Untuk sejumlah besar data, biasanya lebih tidak efisien untuk SQL Server untuk membangun indeks sekaligus daripada data dimuat ke dalam tabel. Sepertinya Anda memasukkan 695 baris ke tabel dengan 11500 baris, jadi saya tidak akan merekomendasikan teknik ini.
6. Pertimbangkan TF 610
Trace Flag 610 memungkinkan penebangan minimal dalam beberapa skenario tambahan. Untuk tabel Anda dengan IDENTITY
kunci berkerumun, Anda akan mendapatkan pendataan minimal untuk setiap halaman data baru selama model pemulihan Anda sederhana atau sebagian besar dicatat. Saya percaya fitur ini tidak aktif secara default karena dapat menurunkan kinerja pada beberapa sistem. Anda perlu menguji dengan cermat sebelum mengaktifkan tanda jejak ini. Referensi Microsoft yang direkomendasikan masih tampak sebagai Panduan Kinerja Pemuatan Data
Dampak I / O dari Penebangan Minimal di Bawah Bendera Jejak 610
Ketika Anda melakukan transaksi pemuatan massal yang dicatat minimal, semua halaman yang dimuat harus dibuang ke disk sebelum komit selesai. Halaman memerah yang tidak tertangkap oleh operasi pos pemeriksaan sebelumnya dapat membuat banyak I / O acak. Bandingkan ini dengan operasi yang sepenuhnya dicatat, yang menciptakan I / O berurutan pada log dan sebagai gantinya tidak memerlukan halaman yang dimuat untuk dibuang ke disk pada waktu yang ditentukan.
Jika skenario beban Anda adalah operasi penyisipan kecil pada btrees yang tidak melewati batas pos pemeriksaan, dan Anda memiliki sistem I / O yang lambat, menggunakan pencatatan minimum sebenarnya dapat memperlambat kecepatan penyisipan.
Sejauh yang saya tahu ini tidak ada hubungannya dengan jejak bendera 610, melainkan dengan logging minimal. Saya percaya kutipan sebelumnya tentang ROWS_PER_BATCH
penyetelan mendapatkan konsep yang sama.
Sebagai kesimpulan, mungkin tidak banyak yang dapat Anda lakukan untuk menyetel lagu Anda BULK INSERT
. Saya tidak akan khawatir tentang hitungan baca yang Anda amati dengan sisipan Anda. SQL Server akan melaporkan pembacaan kapan saja Anda memasukkan data. Pertimbangkan yang berikut ini sangat sederhana INSERT
:
DROP TABLE IF EXISTS X_TABLE;
CREATE TABLE X_TABLE (
VAL VARCHAR(1000) NOT NULL
);
SET STATISTICS IO, TIME ON;
INSERT INTO X_TABLE WITH (TABLOCK)
SELECT REPLICATE('Z', 1000)
FROM dbo.GetNums(10000); -- generate 10000 rows
Output dari SET STATISTICS IO, TIME ON
:
Tabel 'X_TABLE'. Pindai hitungan 0, bacaan logis 11428
Saya memiliki 11.428 yang dilaporkan dibaca tetapi itu bukan informasi yang bisa ditindaklanjuti. Terkadang jumlah pembacaan yang dilaporkan dapat dikurangi dengan pencatatan minimum, tetapi tentu saja perbedaannya tidak dapat langsung diterjemahkan ke dalam peningkatan kinerja.