Menambahkan kolom ke tabel produksi

28

Apa cara terbaik untuk menambahkan kolom ke tabel produksi besar di SQL Server 2008 R2? Menurut buku-buku Microsoft online:

Perubahan yang ditentukan dalam ALTER TABLE diimplementasikan segera. Jika perubahan memerlukan modifikasi pada baris dalam tabel, ALTER TABLE memperbarui baris. ALTER TABLE mendapatkan kunci skema modifikasi di atas meja untuk memastikan bahwa tidak ada koneksi lain referensi bahkan metadata untuk tabel selama perubahan, kecuali operasi indeks online yang membutuhkan kunci SCH-M sangat pendek di akhir.

(http://msdn.microsoft.com/en-us/library/ms190273.aspx)

Di atas meja besar dengan jutaan baris, ini bisa memakan waktu cukup lama. Apakah mengambil pemadaman satu-satunya pilihan? Apa cara terbaik untuk menangani situasi seperti ini?

sh-beta
sumber
1
Artikel terbaru mengenai masalah ini: sqlservercentral.com/articles/Change+Tracking/74397
8kb

Jawaban:

27

"Tergantung"

Jika Anda menambahkan kolom yang tidak perlu menambahkan data ke baris, maka itu bisa sangat cepat.

Misalnya, menambahkan int atau char membutuhkan gerakan baris fisik. Menambahkan nullable varchar tanpa default seharusnya tidak (kecuali bitmap NULL perlu diperluas)

Anda perlu mencobanya pada salinan produksi yang dipulihkan untuk mendapatkan perkiraan

Membuat tabel baru, menyalin, mengganti nama mungkin membutuhkan waktu lebih lama jika Anda harus menambahkan kembali indeks dan kunci pada satu miliar tabel baris.

Saya telah mengubah miliar tabel baris yang membutuhkan waktu beberapa detik untuk menambahkan kolom yang dapat dibatalkan.

Apakah saya mengatakan untuk mengambil cadangan terlebih dahulu?

gbn
sumber
2
+1 pada cadangan. dan pastikan Anda memiliki ruang log yang cukup juga.
SqlACID
Bisakah Anda menjelaskan mengapa menambahkan int atau char memerlukan gerakan baris fisik?
sh-beta
5
Apakah maksud Anda "tidak" perlu menambahkan data ke baris di baris kedua Anda?
Ben Brocka
21

Jika kolom NULLable, dampaknya harus diabaikan. Jika kolom tidak bisa NULL dan nilainya harus ditetapkan, maka itu bisa sangat berbeda. Apa yang akan saya lakukan dalam kasus ini adalah, alih-alih menambahkan batasan tidak nol dan standar dalam satu kesempatan, secara efektif menambahkan data ke setiap baris:

  • tambahkan kolom sebagai NULLable - harus cepat dalam banyak kasus
  • perbarui nilai ke standar
    • Anda dapat melakukan ini dalam batch jika perlu
    • Anda juga dapat menggunakan ini untuk menerapkan logika kondisional di mana beberapa baris mungkin tidak mendapatkan default
  • tambahkan batasan tidak nol / standar
    • ini akan lebih cepat ketika tidak ada data yang NULL, tetapi harus tetap dapat diukur

Setuju dengan @gbn bahwa Anda dapat menguji ini dengan mengembalikan salinan produksi dan mencobanya di sana ... Anda akan mendapatkan ide yang bagus tentang waktu (dengan asumsi perangkat keras agak mirip) dan Anda juga dapat melihat dampaknya pada log transaksi.

Aaron Bertrand
sumber
Kembali sedikit terakhir: •add the not null/default constraintsSaya tidak yakin tidak ada masalah potensial dengan ini ... Ketika MSSQL (bahkan 2008R2) mengubah kolom bukan nol menjadi nol, jika Anda melacak, Anda dapat melihatnya benar-benar di bawah selimut melakukan pembaruan penuh dari setiap baris tabel, yaitu update table1 set column1 = column1saya menganggap itu melakukan verifikasi tidak-nol dengan cara yang benar-benar bodoh. Transaksi ini dua kali ukuran tabel (sebelum dan sesudah halaman) sehingga untuk tabel DW bisa sangat besar. Sebelumnya kami harus mengeluarkan data bcp, memotong, melakukan perubahan null ke non-null, lalu bcp masuk
Jika ada yang tahu cara mengatasi hal ini, saya suka tahu ... Sebaliknya, di Oracle, mengubah nol menjadi tidak nol mengunci, lalu memilih untuk memverifikasi tidak bukan nol, maka pembaruan data meta murni sesaat.
Hai @ Mike, ini sepertinya pertanyaan potensial yang bagus dengan sendirinya.
Derek Downey
4

Sudahkah Anda mempertimbangkan:

  1. Membuat tabel baru yang menyertakan perubahan definisi tabel.
  2. Memasukkan ke definisi tabel baru memilih dari tabel asli.
  3. Mengganti nama tabel asli menjadi _orig dan kemudian mengubah nama tabel baru ke nama tabel asli.

Kerugiannya di sini adalah Anda harus memiliki ruang yang cukup dalam database untuk melakukan perubahan ini. Anda mungkin masih memerlukan kunci baca di atas meja untuk mencegah pembacaan yang kotor.

Namun, Anda meminimalkan dampaknya kepada pengguna akhir jika ada kesempatan atau kebutuhan untuk tabel asli untuk diakses secara bersamaan. Ini juga harus meminimalkan durasi kunci.

RobPaller
sumber
Tidakkah Anda membutuhkan kunci tulis , daripada membaca? Tidak apa-apa bagi pengguna untuk melihat data di tabel lama, Anda hanya tidak ingin mereka melakukan perubahan apa pun yang akan ditimpa ketika Anda menyelesaikan swap buffer.
Jon of All Trades
Itulah yang saya pikirkan dengan topi gudang data saya di mana perubahan dapat dikontrol sedikit lebih mudah. Dalam situasi OLTP Anda benar, kunci tulis akan diperlukan untuk menghindari perubahan yang dibuat ke tabel.
RobPaller