it-swarm.asia

SQL Server "tabel kosong" lambat setelah menghapus semua (12 juta) catatan?

Saya punya contoh SQL Server 2008 dengan sekitar 150 kolom. Saya sebelumnya telah mengisi tabel ini dengan sekitar 12 juta entri, tetapi sejak itu membersihkan tabel dalam persiapan untuk set data baru.

Namun, perintah yang pernah dijalankan secara instan di tabel kosong seperti count(*) dan select top 1000 di SQL Management Studio sekarang butuh ribuan tahun untuk dijalankan.

SELECT COUNT(*) FROM TABLE_NAME 

butuh lebih dari 11 menit untuk mengembalikan 0, dan SELECT TOP 1000 butuh hampir 10 menit untuk mengembalikan meja kosong.

Saya juga memperhatikan bahwa ruang kosong pada hard drive saya benar-benar menghilang (turun dari sekitar 100G ke 20G). Satu-satunya hal yang terjadi di antaranya adalah satu kueri yang saya jalankan:

DELETE FROM TABLE_NAME

Apa yang sedang terjadi?!?

27
TheDramaLlama

Anda telah diberi tahu tentang mengapa TRUNCATE akan jauh lebih cepat/lebih baik/lebih seksi daripada DELETE, tetapi masih ada pertanyaan yang harus diatasi:

Mengapa SELECT lebih lambat setelah DELETE selesai ?

Itu karena DELETE hanya memiliki ghosted baris. Tabel ini hanya sebesar ketika memiliki 12M baris, meskipun tidak ada. Untuk menghitung baris (0), diperlukan waktu sebanyak yang diperlukan untuk menghitung 12M baris. Pada waktunya, proses pembersihan hantu akan mengumpulkan sampah catatan hantu ini dan membatalkan alokasi halaman yang berisi hanya hantu , dan SELECT Anda akan mempercepat. Tetapi sekarang jika Anda memeriksa Skipped Ghosted Records/sec di perfmon mungkin meroket selama SELECT COUNT(*). Anda juga dapat mempercepat beberapa hal dengan membangun kembali tabel: ALTER TABLE ... REBUILD.

TRUNCATE juga akan menangani masalah ini, karena tidak meninggalkan hantu.

Lihat juga Di dalam Mesin Penyimpanan: Pembersihan hantu secara mendalam .

42
Remus Rusanu

DELETE pernyataan menghapus baris dari tabel satu per satu, mencatat setiap baris dalam transaction log, serta mempertahankan informasi log sequence number (LSN). Karena Anda menyebutkan meja Anda memiliki data yang sangat besar (12 juta catatan), setelah penghapusan yang mana hard disk Anda kehabisan ruang, periksa ukuran file Log Database Anda. Kemungkinan besar akan tumbuh.

cara yang lebih baik adalah:

TRUNCATE TABLE_NAME
13
Akhil

(Awalnya ini adalah komentar untuk jawaban @ DaveE, tapi saya sudah memasukkannya ke dalam jawabannya sendiri karena sudah lama)

TRUNCATE adalah operasi yang dicatat. Itu harus dinyatakan tidak sesuai ACID. Namun, perbedaan antara TRUNCATE dan DELETE:

  • Penggunaan ruang log: TRUNCATE hanya mencatat halaman/luasan * dibebaskan, sedangkan DELETE mencatat setiap baris.
  • Penggunaan kunci: TRUNCATE umumnya akan menggunakan lebih sedikit kunci, karena dibutuhkan kunci tabel dan kunci halaman, berbeda dengan DELETE yang menggunakan kunci baris **.
  • IDENTITY urutan: TRUNCATE mengatur ulang urutan identitas pada tabel, jika ada.

(* Tingkat = 8 halaman. TRUNCATE akan mencatat/menghapus luasan jika semuanya dari satu tabel itu, jika tidak maka akan mencatat/menghapus halaman dari luasan campuran.

** Satu efek samping dari ini adalah DELETE FROM TABLE berpotensi meninggalkan halaman kosong yang dialokasikan ke tabel, tergantung pada apakah operasi bisa mendapatkan kunci tabel eksklusif atau tidak.)

Jadi (kembali ke pertanyaan awal), TRUNCATE TABLE secara konklusif lebih baik daripada DELETE FROM TABLE jika Anda mengosongkan tabel tetapi ingin mempertahankan strukturnya (NB: TRUNCATE tidak dapat digunakan pada tabel yang dirujuk oleh kunci asing dari tabel lain).

Seperti tercantum dalam komentar @ Tullo, periksa juga model pemulihan basis data Anda - jika penuh, maka Anda harus mulai mengambil cadangan log, atau mengubah model pemulihan menjadi sederhana. Setelah Anda melakukan salah satu dari itu, Anda mungkin ingin mengecilkan file log Anda sebagai operasi sekali saja (NB: file log - hanya) untuk mendapatkan kembali semua ruang kosong itu.

Akhirnya, hal lain yang perlu diperhatikan - tabel statistik. Lari UPDATE STATISTICS <TABLENAME>' afterMEMOTONG/DELETE` sehingga pengoptimal kueri tidak tersandung oleh statistik lama.

3
Simon Righarts

(CATATAN: Saya bukan DBA) DELETE adalah operasi yang dicatat, dan tidak membebaskan ruang yang digunakan. Anda mungkin memiliki log transaksi besar yang mengambil ruang dan pemindaian tabel berjalan di ruang tabel 'kosong'. Saya kira Anda perlu menghapus log transaksi dan mengecilkan basis data Anda. Artikel StackOverflow ini harus Anda mulai.

Dan gunakan TRUNCATE TABLE ketika Anda ingin melakukan ini di masa depan.

EDIT: Pernyataan saya tentang TRUNCATE yang tidak dicatat salah. dihapus.

2
DaveE