Mentransfer data dalam jumlah besar (84 juta baris) secara efisien

11

Saya memiliki sekitar 84 juta baris. Dari mereka semua perlu ditransfer ke database terpisah di server yang sama, maka saya hapus untuk menghapus sekitar 60 juta baris dari sumber database.

84 juta baris semuanya berada di tabel yang sama. Tabel itu saja menyumbang 90% dari seluruh database.

Jadi ... Sumber: 84 juta baris -> 24 juta baris Tujuan: 0 baris -> 84 juta baris

Sumber menjalankan mode pemulihan penuh, tujuan akan berjalan sederhana.

Saya bertanya-tanya apa cara paling efisien untuk melakukan ini?

Paket A:

1) Masukkan ke tujuan SELECT * DARI sumber

2) Sumber TRUNCATE

3) Masukkan ke dalam sumber PILIH * DARI tujuan DI MANA keep_condition = 1

Rencana B:

1) Kembalikan cadangan basis data sumber sebagai basis data tujuan

2) Jatuhkan setiap tabel kecuali yang dibutuhkan pada database tujuan

3) Sumber TRUNCATE

4) MASUKKAN KE sumber SELECT * DARI tujuan DI MANA keep_condition = 1

Paket C:

1) Masukkan ke tujuan SELECT * DARI sumber

2) DELETE source WHERE keep_condition = 0

atau sesuatu yang lain?

Terima kasih

elty123
sumber
mengapa Anda tidak menggunakan panduan Impor dan Ekspor Data? itu adalah alat yang disediakan dengan instalasi SQL Server.
Hani El Mouallem
Apakah mungkin untuk menyalin baris 24 juta ke tabel baru, lalu cukup mengganti nama keduanya sesuai kebutuhan sehingga Anda tidak perlu memindahkan 84 juta baris secara tidak perlu?
LowlyDBA
Apakah ini proses satu kali atau sedang berjalan? Saya bertanya karena, mengingat waktu yang diperlukan untuk memproses 80 juta baris, kemungkinan akan ada perubahan data dalam SOURCE yang menghasilkan baris yang sekarang harus hidup dalam DESTINASI.
Michael Green
Ini terlihat seperti masalah XY: Anda harus berakhir dengan semua baris 84MM dalam satu DB, dan 24MM dari mereka dalam DB kedua. Apa persyaratan bisnis yang mengharuskan 84MM dipindahkan dan 60M dihapus, bukan hanya memindahkan 24MM? tautan: meta.stackexchange.com/questions/66377/what-is-the-xy-problem )
Pieter Geerkens
Saya memiliki masalah yang sangat mirip dan jelas bukan XY. Sebelum proliferasi undang-undang tentang penyimpanan catatan, kami menyimpan semua data. Sekarang kita harus menghapus baris yang lebih lama dari tanggal kita diharuskan secara hukum untuk menyimpannya. Ini berarti pengarsipan dan penghapusan data selama lebih dari 20 tahun karena retensi hukum dalam kebanyakan kasus adalah 7 tahun. Saya tidak berpikir saya sendirian dalam percaya Microsoft lalai dalam tidak menyediakan fungsionalitas 'salinan massal' untuk prosedur tersimpan. Sebuah aplikasi tidak boleh lebih cepat pada pergerakan data 'dalam' suatu DB daripada DB itu sendiri. Tahun depan tahun lain harus diarsipkan.
bielawski

Jawaban:

11

Saya akan menambahkan bahwa, namun Anda memutuskan untuk melakukan pendekatan ini, Anda harus mengelompokkan transaksi ini . Saya sangat beruntung dengan artikel yang ditautkan belakangan ini, dan saya menghargai cara memanfaatkan indeks sebagai lawan dari sebagian besar solusi batch yang saya lihat.

Bahkan dengan penebangan minimal, itu adalah transaksi besar , dan Anda bisa menghabiskan banyak waktu berurusan dengan konsekuensi dari pertumbuhan log yang abnormal (VLF, pemotongan, ukuran kanan, dll.).

Terima kasih

Erik Darling
sumber
3

"Efisien" dapat berlaku untuk penggunaan file log, kinerja I / O, waktu CPU atau waktu eksekusi.

Saya akan mencoba untuk mencapai operasi penebangan minimal, yang akan cukup efisien dari sudut pandang logging. Ini akan menghemat waktu eksekusi Anda sebagai bonus. Jika Anda memiliki ruang tempdb, berikut ini mungkin cocok untuk Anda.

CREATE TABLE #temp;
ALTER source -> BULK_LOGGED recovery model

BEGIN TRANSACTION;

    INSERT INTO dest SELECT FROM source;
    INSERT INTO #temp SELECT FROM source WHERE keep_condition=1;
    TRUNCATE TABLE source;
    INSERT INTO source SELECT FROM #temp;

COMMIT TRANSACTION;

ALTER source -> FULL recovery model
DROP TABLE #temp;

Agar operasi yang dicatat minimal terjadi, sejumlah kondisi harus benar, termasuk tidak ada cadangan yang sedang berjalan, basis data diatur ke BULK_LOGGEDmode pemulihan, dan tergantung pada indeks Anda, tabel target mungkin harus kosong. Beberapa perilaku ini juga berubah (ditingkatkan) dari SQL Server 2005 ke 2008.

Kemudian lagi, tanpa mengetahui spesifikasi tabel dan data Anda, salah satu opsi lain Anda mungkin berkinerja lebih baik. Coba gunakan

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

.. dan lihat mana yang paling baik.

EDIT : Saat melakukan operasi yang dicatat dalam jumlah besar, pastikan Anda membuat cadangan (log lengkap atau transaksi) sebelum dan setelah operasi jika Anda memerlukan kemampuan pemulihan point-in-time dan Anda curiga ada aktivitas lain yang mungkin terjadi dalam database di saat yang sama saat pekerjaan ETL Anda berjalan.

Saya menulis posting blog tentang operasi yang sedikit dicatat beberapa waktu lalu, ada tautan di sana ke posting dan dokumentasi lain.

Daniel Hutmacher
sumber
+1 untuk menasihati OP untuk menguji untuk melihat mana yang berkinerja lebih baik. Tentu saja, itu mungkin agak sulit untuk mendapatkan bilangan real kecuali jika dia memiliki sistem duplikat di dev, dll.
Max Vernon
Hanya sebuah pertanyaan, Apa yang akan terjadi jika Anda mencoba melakukan pemulihan waktu ketika basis data dalam mode log massal? Saya menduga setiap transaksi yang tidak memenuhi syarat sebagai "bulk" akan dapat dipulihkan.
elty123
1
@ elty123 Dalam pemulihan log massal Anda hanya dapat mengembalikan ke akhir cadangan log terakhir. Tidak ada gunanya pemulihan waktu seperti akan ada dengan pemulihan penuh. Biasanya Anda beralih ke pemulihan login massal, menjalankan beberapa proses ETL, beralih kembali ke penuh dan kemudian mengambil cadangan log.
RubberChickenLeader
@ WindRaven Ini tidak benar - lihat jawaban saya di bawah ini.
wBob
1
@ wBob dan @WindRaven, saya telah memperbarui jawaban saya untuk mencerminkan kebutuhan untuk mengambil cadangan sebelum dan sesudah menggunakan BULK_LOGGEDmode. Terima kasih!
Daniel Hutmacher
1

Kenapa tidak BCP?

  1. Cadangkan sumbernya b
  2. Ubah sourcedb menjadi login massal
  3. Buka command prompt

  4. bcp server.sourcedb.table out Filename.flt -T -c

  5. bcp "SELECT * FROM sourcedb.table WHERE keep_condition = 1" queryout Filename2.flt -T -c

  6. bcp Server.destinationdb.table in Filename.flt -T -c -b1000

  7. periksa datanya

  8. Dari SSMS Truncate the sourcedb table
  9. bcp server.sourcedb.table in Filename2.flt -T -c -b1000
  10. Ubah sourcedb kembali menjadi penuh
stacylaray
sumber
2
Karena mereka berada di server yang sama. Menulis ke sistem file akan mahal. Lebih baik buat database dan presize, semoga memanfaatkan inisialisasi file instan. Ini akan menjadi pilihan yang masuk akal untuk dbs di server yang berbeda meskipun SSIS akan menjadi pilihan pertama saya jika tersedia. NB: Opsi -n (asli) lebih ringkas dan lebih aman untuk memindahkan data dari SQL Server ke SQL Server. Opsi -b tidak berpengaruh untuk bcp out.
wBob
0

Jangan berpikir Anda harus merekomendasikan mengubah model pemulihan tanpa cadangan database lengkap atau cadangan t-log sebelum dan sesudah . Salah satu fitur dari model pemulihan BULK_LOGGED adalah bahwa Anda akan kehilangan kemampuan untuk melakukan pemulihan point-in-time untuk t-log yang berisi operasi yang dicatat secara massal. Skenario klasik: backup penuh setiap malam, backup t-log setiap jam. Anda mengubah model pemulihan menjadi log-massal dan memulai operasi Anda. Terjadi kesalahan dan transaksi dibatalkan (atau Anda belum pernah menggunakannya). Namun Anda tidak yakin apa lagi yang terjadi di database sehingga Anda ingin mengembalikan ke titik yang diketahui baik.

Kapan Anda dapat mengembalikan kembali ke? Cadangan t-log terakhir setiap jam yang tidak berisi operasi yang dicatat dalam jumlah besar, berpotensi kehilangan n menit transaksi. Cadangan penuh atau cadangan t-log sebelum mengubah model pemulihan akan membuat titik mundur. Yang mana yang Anda pilih tergantung pada RTO Anda.

wBob
sumber
0

Menjatuhkan partisi dari tabel adalah cara yang sangat cepat dan hemat sumber daya untuk menghapus potongan data besar dari sebuah tabel. Apakah tabel ini dipartisi dengan cara yang mendukung sumber / tujuan Anda membagi jawabannya adalah untuk mengembalikan salinan, jatuhkan tabel redundan dan partisi redundan dari tujuan dan jatuhkan partisi pelengkap dari sumber.

Namun, biaya untuk mengaktifkan partisi mungkin menjadikan ini operasi yang lebih mahal secara keseluruhan.

Michael Green
sumber