Saya telah menemukan beberapa sumber yang menyatakan ALTER TABLE ... DROP COLUMN adalah operasi meta-data saja.
Bagaimana ini bisa terjadi? Apakah data selama DROP COLUMN tidak perlu dibersihkan dari indeks yang tidak berkerumun dan indeks / tumpukan berkerumun?
Selain itu, mengapa Microsoft Documents menyiratkan bahwa itu adalah operasi yang sepenuhnya dicatat?
Modifikasi yang dilakukan pada tabel dicatat dan sepenuhnya dapat dipulihkan. Perubahan yang memengaruhi semua baris dalam tabel besar, seperti menjatuhkan kolom atau, pada beberapa edisi SQL Server, menambahkan kolom NOT NULL dengan nilai default, bisa memakan waktu lama untuk menyelesaikan dan menghasilkan banyak catatan log . Jalankan pernyataan ALTER TABLE ini dengan kehati-hatian yang sama seperti pernyataan INSERT, UPDATE, atau DELETE yang memengaruhi banyak baris.
Sebagai pertanyaan sekunder: bagaimana mesin melacak kolom yang jatuh jika data tidak dihapus dari halaman yang mendasarinya?
sumber
Jawaban:
Ada keadaan tertentu di mana menjatuhkan kolom bisa menjadi operasi meta-data-only. Definisi kolom untuk setiap tabel yang diberikan tidak termasuk dalam setiap halaman di mana baris disimpan, definisi kolom hanya disimpan dalam metadata database, termasuk sys.sysrowsets, sys.sysrscols, dll.
Ketika menjatuhkan kolom yang tidak direferensikan oleh objek lain, mesin penyimpanan hanya menandai definisi kolom sebagai tidak lagi hadir dengan menghapus rincian terkait dari berbagai tabel sistem. Tindakan menghapus meta-data membatalkan cache prosedur, mengharuskan kompilasi ulang setiap kali kueri selanjutnya referensi tabel itu. Karena kompilasi hanya mengembalikan kolom yang saat ini ada dalam tabel, detail kolom untuk kolom yang dijatuhkan bahkan tidak pernah diminta; mesin penyimpanan melewatkan byte yang disimpan di setiap halaman untuk kolom itu, seolah-olah kolom itu tidak ada lagi.
Ketika operasi DML berikutnya terjadi terhadap tabel, halaman yang terpengaruh ditulis ulang tanpa data untuk kolom yang dijatuhkan. Jika Anda membangun kembali indeks berkerumun atau tumpukan, semua byte untuk kolom yang dijatuhkan secara alami tidak ditulis kembali ke halaman pada disk. Ini secara efektif menyebarkan beban menjatuhkan kolom dari waktu ke waktu, membuatnya kurang terlihat.
Ada beberapa situasi di mana Anda tidak bisa menjatuhkan kolom, seperti ketika kolom dimasukkan dalam indeks, atau ketika Anda secara manual membuat objek statistik untuk kolom. Saya menulis posting blog yang menunjukkan kesalahan yang disajikan ketika mencoba mengubah kolom dengan objek statistik yang dibuat secara manual. Semantik yang sama berlaku ketika menjatuhkan kolom - jika kolom direferensikan oleh setiap objek lain, tidak bisa begitu saja dijatuhkan. Objek referensi harus diubah terlebih dahulu, kemudian kolom bisa dijatuhkan.
Ini cukup mudah untuk ditampilkan dengan melihat isi dari log transaksi setelah menjatuhkan kolom. Kode di bawah ini membuat tabel dengan satu kolom char panjang 8.000. Ia menambahkan satu baris, kemudian menjatuhkannya, dan menampilkan isi dari log transaksi yang berlaku untuk operasi drop. Catatan log menunjukkan modifikasi ke berbagai tabel sistem tempat definisi tabel dan kolom disimpan. Jika data kolom sebenarnya dihapus dari halaman yang dialokasikan untuk tabel, Anda akan melihat catatan log merekam data halaman yang sebenarnya; tidak ada catatan seperti itu.
(Outputnya terlalu besar untuk ditampilkan di sini, dan dbfiddle.uk tidak akan mengizinkan saya mengakses fn_dblog)
Set output pertama menunjukkan log sebagai hasil dari pernyataan DDL menjatuhkan kolom. Set output kedua menunjukkan log setelah menjalankan pernyataan DML tempat kami memperbarui
rid
kolom. Di set hasil kedua, kita melihat catatan log yang menunjukkan penghapusan terhadap dbo.DropColumnTest, diikuti oleh masukkan ke dbo.DropColumnTest. Setiap Panjang Catatan Log adalah 8116, menunjukkan halaman yang sebenarnya telah diperbarui.Seperti yang dapat Anda lihat dari output dari
fn_dblog
perintah dalam tes di atas, seluruh operasi yang sepenuhnya login. Ini berlaku untuk pemulihan sederhana, serta pemulihan penuh. Terminologi "sepenuhnya dicatat" mungkin disalahartikan karena modifikasi data tidak dicatat. Ini bukan apa yang terjadi - modifikasi adalah login, dan dapat sepenuhnya digulung kembali. Log hanya merekam halaman-halaman yang disentuh, dan karena tidak ada halaman data tabel yang dicatat oleh operasi DDL, baik ituDROP COLUMN
, dan setiap rollback yang mungkin terjadi akan terjadi dengan sangat cepat, terlepas dari ukuran tabel.Untuk sains , kode berikut akan membuang halaman data untuk tabel yang termasuk dalam kode di atas, menggunakan
DBCC PAGE
, gaya "3". Gaya "3" menunjukkan kami menginginkan tajuk halaman plus interpretasi per baris terperinci . Kode menggunakan kursor untuk menampilkan detail untuk setiap halaman dalam tabel, jadi Anda mungkin ingin memastikan Anda tidak menjalankan ini pada tabel besar.Melihat output untuk halaman pertama dari demo saya (setelah kolom dijatuhkan, tetapi sebelum kolom diperbarui), saya melihat ini:
Saya telah menghapus sebagian besar dump halaman mentah dari output yang ditunjukkan di atas untuk singkatnya. Di akhir output, Anda akan melihat ini untuk
rid
kolom:Baris terakhir di atas,,
rid = 1
mengembalikan nama kolom, dan nilai saat ini disimpan dalam kolom di halaman.Selanjutnya, Anda akan melihat ini:
Output menunjukkan bahwa Slot 0 berisi kolom yang dihapus, berdasarkan
DELETED
teks di mana nama kolom biasanya. Nilai kolom dikembalikanNULL
karena kolom telah dihapus. Namun, seperti yang dapat Anda lihat di data mentah, nilai karakter 8.000REPLICATE('Z', 8000)
, untuk kolom itu masih ada di halaman. Ini adalah contoh dari bagian dari output PAGE DBCC:sumber