Saya memiliki tabel data besar. Ada 10 juta catatan dalam tabel ini.
Apa cara terbaik untuk kueri ini
Delete LargeTable where readTime < dateadd(MONTH,-7,GETDATE())
sql-server
sql-server-2008
sql-optimization
pengguna3107343
sumber
sumber
Jawaban:
Jika Anda menghapus Semua baris dalam tabel itu, pilihan paling sederhana adalah memotong tabel, kira-kira seperti itu
Truncate table hanya akan mengosongkan tabel, Anda tidak dapat menggunakan klausa WHERE untuk membatasi baris yang dihapus dan tidak ada pemicu yang akan dipecat.
Di sisi lain jika Anda menghapus lebih dari 80-90 Persen data, katakanlah jika Anda memiliki total 11 Juta baris dan Anda ingin menghapus 10 juta cara lain adalah dengan Memasukkan 1 juta baris ini (catatan yang ingin Anda pertahankan) ) ke meja pementasan lain. Pangkas tabel besar ini dan masukkan kembali 1 Juta baris ini.
Atau jika izin / tampilan atau objek lain yang memiliki tabel besar ini sebagai tabel yang mendasarinya tidak terpengaruh dengan menjatuhkan tabel ini, Anda bisa mendapatkan jumlah baris yang relatif kecil ini ke tabel lain letakkan tabel ini dan buat tabel lain dengan skema yang sama dan impor ini baris kembali ke tabel ex-Large ini.
Satu opsi terakhir yang bisa saya pikirkan adalah mengubah database Anda
Recovery Mode to SIMPLE
dan kemudian menghapus baris dalam batch yang lebih kecil menggunakan loop sementara seperti ini ..dan jangan lupa untuk mengubah mode Pemulihan kembali ke penuh dan saya pikir Anda harus mengambil cadangan untuk membuatnya sepenuhnya efektif (perubahan atau mode pemulihan).
sumber
optimal solution for unknown case
itulah mimpinya bukan? Sayangnya Anda tidak dapat menyembuhkan setiap penyakit dengan satu pil; Saya telah menyarankan beberapa solusi yang mungkin untuk skenario yang berbeda. Sayangnya tidak ada peluru keras di sini.@ m-ali jawaban benar tetapi juga perlu diingat bahwa log dapat tumbuh banyak jika Anda tidak melakukan transaksi setelah setiap chunk dan melakukan pos pemeriksaan. Ini adalah bagaimana saya akan melakukannya dan mengambil artikel ini http://sqlperformance.com/2013/03/io-subsystem/chunk-deletes sebagai referensi, dengan tes kinerja dan grafik:
sumber
COMMIT TRANSACTION
danCHECKPOINT
log masih terus tumbuh. Terima kasih telah menjelaskan ini.@Deleted_Rows
dengan 10.000 atau Anda mungkin berakhir dengan loop tak terhingga karena menghapus data yang tidak terbatas. JadiWHILE (@Deleted_Rows = 10000)
- segera setelah tidak ada "halaman" data lengkap untuk menghapusnya akan berhenti. Dalam implementasi Anda,,WHILE (@Deleted_Rows > 0)
loop-sementara akan mengeksekusi kembali bahkan jika itu hanya menghapus satu baris, dan eksekusi berikutnya mungkin juga menemukan satu atau dua baris untuk dihapus - menghasilkan loop tak terbatas.WHILE
lingkaran itu sendiri:dateadd(MONTH,-7,GETDATE())
.WHILE
loop.Anda juga dapat menggunakan GO + berapa kali Anda ingin menjalankan kueri yang sama.
sumber
GO xx
seharusnya berfungsi? Saya mendapatkan kesalahan "Tidak dapat menemukan prosedur tersimpan ''" . TanpaGO
perintah itu berfungsi dengan baik.@Francisco Goldenstein, hanya koreksi kecil. COMMIT harus digunakan setelah Anda mengatur variabel, jika tidak, WHILE akan dijalankan sekali saja:
sumber
Variasi dari M.Ali ini bekerja dengan baik untuk saya. Menghapus beberapa, menghapus log dan mengulangi. Saya melihat log tumbuh, turun, dan mulai lagi.
sumber
# of rows
untuk menghapus sekaligus, dan jugaWHERE
klausa. Bekerja seperti pesona!Jika Anda bersedia (dan mampu) mengimplementasikan partisi, itu adalah teknik yang efektif untuk menghapus sejumlah besar data dengan sedikit overhead run-time. Namun, tidak hemat biaya untuk latihan sekali saja.
sumber
Saya dapat menghapus 19 juta baris dari meja saya yang terdiri dari 21 juta baris dalam hitungan menit . Ini pendekatan saya.
Jika Anda memiliki kunci primer peningkatan-otomatis pada tabel ini, maka Anda dapat menggunakan kunci utama ini.
Dapatkan nilai minimum kunci utama dari tabel besar tempat readTime <dateadd (MONTH, -7, GETDATE ()). (Tambahkan indeks pada readTime, jika belum ada, indeks ini akan tetap dihapus bersama dengan tabel di langkah 3.). Mari kita simpan dalam variabel 'min_primary'
Masukkan semua baris yang memiliki kunci utama> min_primary ke dalam tabel pementasan (tabel memori jika jumlah baris tidak besar).
Jatuhkan meja besar.
Buat ulang meja. Salin semua baris dari staging table ke tabel utama.
Jatuhkan meja pementasan.
sumber
Anda dapat menghapus kumpulan kecil menggunakan loop sementara, sesuatu seperti ini:
sumber
Penggunaan lain:
Pilihan;
Jika log transaksi diaktifkan, nonaktifkan log transaksi.
sumber
Sintaks yang lebih pendek
sumber
Jika Anda menggunakan SQL server 2016 atau lebih tinggi dan jika tabel Anda memiliki partisi yang dibuat berdasarkan kolom yang Anda coba hapus (misalnya kolom Timestamp), maka Anda bisa menggunakan perintah baru ini untuk menghapus data dengan partisi.
TULANG MEJA DENGAN (PARTISI ({|} [, ... n]))
Ini akan menghapus data hanya di partisi yang dipilih dan harus menjadi cara paling efisien untuk menghapus data dari bagian tabel karena tidak akan membuat log transaksi dan akan dilakukan secepat pemotongan biasa tetapi tanpa menghapus semua data dari meja.
Kekurangannya adalah jika meja Anda tidak disetel dengan partisi, maka Anda harus menggunakan jadul dan menghapus data dengan pendekatan reguler dan kemudian membuat ulang tabel dengan partisi sehingga Anda bisa melakukan ini di masa depan, itulah yang saya lakukan. Saya menambahkan pembuatan partisi dan penghapusan ke dalam prosedur penyisipan itu sendiri. Saya punya meja dengan 500 juta baris jadi ini adalah satu-satunya pilihan untuk mengurangi waktu penghapusan.
Untuk detail lebih lanjut lihat tautan di bawah ini: https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-2017
SQL server 2016 Tabel terpotong dengan partisi
Di bawah ini adalah apa yang saya lakukan pertama kali untuk menghapus data sebelum saya bisa membuat ulang tabel dengan partisi dengan data yang diperlukan di dalamnya. Kueri ini akan berjalan selama berhari-hari selama jendela waktu yang ditentukan hingga data dihapus.
sumber
Jika saya katakan tanpa loop, saya bisa menggunakan
GOTO
pernyataan untuk menghapus sejumlah besar catatan menggunakan sql server. exa.seperti cara ini Anda dapat menghapus sejumlah besar data dengan ukuran penghapusan yang lebih kecil.
beri tahu saya jika memerlukan informasi lebih lanjut.
sumber