Satu-satunya cara yang masuk akal untuk memperbarui tabel 120 juta catatan adalah dengan SELECT
pernyataan yang mengisi detik meja. Anda harus berhati-hati saat melakukan ini. Petunjuk di bawah ini.
Kasus Sederhana
Untuk tabel tanpa indeks berkerumun, selama waktu tanpa DML bersamaan:
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- membuat ulang indeks, batasan, dll di tabel baru
- ganti lama dan baru dengan ALTER SKEMA ... TRANSFER.
- jatuhkan meja lama
Jika Anda tidak dapat membuat skema klon, nama tabel yang berbeda dalam skema yang sama akan digunakan. Ingatlah untuk mengganti nama semua batasan dan pemicu Anda (jika ada) setelah peralihan.
Kasus Tidak Sederhana
Pertama, buat ulang BaseTable
. Anda dengan nama yang sama di bawah skema yang berbeda, misalnya clone.BaseTable
. Menggunakan skema terpisah akan menyederhanakan proses penggantian nama nanti.
- Sertakan indeks berkerumun , jika berlaku. Ingatlah bahwa kunci utama dan batasan unik dapat dikelompokkan, tetapi tidak harus demikian.
- Sertakan kolom identitas dan kolom yang dihitung , jika berlaku.
- Sertakan kolom INT baru Anda , di mana pun tempatnya.
- Jangan sertakan salah satu dari berikut ini:
- pemicu
- kendala kunci asing
- indeks non-clustered/kunci utama/batasan unik
- periksa batasan atau batasan default. Default tidak membuat banyak perbedaan, tetapi kami mencoba untuk menjaga agar tetap minimal.
Kemudian, uji sisipan Anda dengan 1000 baris:
-- assuming an IDENTITY column in BaseTable
SET IDENTITY_INSERT clone.BaseTable ON
GO
INSERT clone.BaseTable WITH (TABLOCK) (Col1, Col2, Col3)
SELECT TOP 1000 Col1, Col2, Col3 = -1
FROM dbo.BaseTable
GO
SET IDENTITY_INSERT clone.BaseTable OFF
Periksa hasilnya. Jika semuanya muncul secara berurutan:
- memotong tabel kloning
- pastikan database masuk dalam log massal atau model pemulihan sederhana
- lakukan penyisipan penuh.
Ini akan memakan waktu cukup lama, tetapi tidak selama pembaruan. Setelah selesai, periksa data di tabel kloning untuk memastikan semuanya sudah benar.
Kemudian, buat ulang semua kunci utama non-cluster/konstrain/indeks unik dan batasan kunci asing (dalam urutan itu). Buat ulang default dan periksa batasan, jika berlaku. Buat ulang semua pemicu. Buat ulang setiap batasan, indeks, atau pemicu dalam kumpulan terpisah. misalnya:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Terakhir, pindahkan dbo.BaseTable
ke skema cadangan dan clone.BaseTable
ke skema dbo (atau di mana pun meja Anda seharusnya hidup).
-- -- perform first true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
-- GO
-- -- create a backup schema, if necessary
-- CREATE SCHEMA backup_20100914
-- GO
BEGIN TRY
BEGIN TRANSACTION
ALTER SCHEMA backup_20100914 TRANSFER dbo.BaseTable
-- -- perform second true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
ALTER SCHEMA dbo TRANSFER clone.BaseTable
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() -- add more info here if necessary
ROLLBACK TRANSACTION
END CATCH
GO
Jika Anda perlu mengosongkan ruang disk, Anda dapat menjatuhkan tabel asli Anda saat ini, meskipun mungkin lebih bijaksana untuk menyimpannya lebih lama.
Tak perlu dikatakan, ini idealnya offline operasi. Jika Anda memiliki orang yang memodifikasi data saat Anda melakukan operasi ini, Anda harus melakukan operasi yang benar dengan sakelar skema. Saya sarankan membuat pemicu di dbo.BaseTable
untuk mencatat semua DML ke tabel terpisah. Aktifkan pemicu ini sebelum Anda memulai penyisipan. Kemudian dalam transaksi yang sama saat Anda melakukan transfer skema, gunakan tabel log untuk melakukan perbaikan. Uji ini terlebih dahulu pada subset data! Delta mudah dikacaukan.