Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Mempersempit Tipe Data pada tabel yang sangat besar

Pertama, terima kasih telah melakukan ini. Ini adalah kemenangan yang jelas sehingga banyak yang tidak melihat banyak nilai, tetapi itu akan sangat berharga :). Membuat dunia sedikit lebih waras.

Mengenai IsActive menjadi boolean. Dugaan saya adalah Anda berpikir untuk menjadikannya BIT bidang. Itu mungkin cara yang harus dilakukan, tetapi terkadang lebih baik menggunakan TINYINT karena ada kemungkinan memperluas makna menjadi lebih dari 2 keadaan. Dalam hal ini benar-benar menjadi lebih dari StatusID . Biasanya ini adalah kasus sesuatu yang dimulai secara sederhana sebagai Aktif / Tidak aktif , tapi nanti mungkin Dihapus dan/atau lainnya. Dari perspektif ukuran, TINYINT selalu 1 byte. Sebaliknya, BIT adalah 1 byte hingga 8 BIT bidang . Artinya, satu BIT bidang adalah 1 byte, 2 BIT bidang juga satu byte, dan seterusnya hingga 8 BIT bidang yang disimpan dalam satu byte. Jadi, tidak ada penghematan ruang memilih BIT lebih dari TINYINT ketika tabel hanya memiliki 1 BIT bidang. Hanya sesuatu yang perlu dipertimbangkan.

Melakukan ALTER TABLE agak banyak untuk tabel besar, seperti yang Anda lihat. Salah satu opsi, meskipun tidak bagus, adalah menambahkan NOT NULL bidang--Number_1new --dengan DEFAULT value (ini akan terjadi seketika karena default, setidaknya dimulai dengan SQL 2012) yang tidak dimiliki secara alami (misalnya 255), dan kemudian secara perlahan memigrasikan nilai, dalam satu lingkaran, seperti pada:

UPDATE TOP (5000) tab
SET tab.Number_1new = tab.Number_1
FROM [table] tab
WHERE tab.Number_1new = 255;

Dan jika sudah selesai lakukan:

sp_rename 'table.Number_1', 'Number_1old', 'COLUMN';
sp_rename 'table.Number_1new', 'Number_1', 'COLUMN';

Tentu saja, yang terbaik adalah membungkusnya dalam TRANSAKSI, dan membungkusnya dengan TRY / CATCH. Ketika kode terkait telah diperbarui dan semuanya telah diuji dan data terlihat bagus, maka Anda dapat melepaskan Number_1old kolom.

Namun, cara terbaik yang saya temukan adalah membuat tabel baru, perlahan-lahan mentransisikan data, lalu menukar tabel dan kode secara bersamaan. Saya merinci langkah-langkahnya dalam artikel di SQL Server Central:Restrukturisasi 100 Juta Baris (atau lebih) Tabel dalam Detik. SRSLY! (perlu pendaftaran gratis). Untuk berjaga-jaga jika ada masalah dalam mengakses artikel tersebut, berikut adalah langkah-langkah dasarnya:

  1. Buat tabel baru dengan struktur ideal--[tableNew]. Jika Anda menggunakan Edisi Perusahaan, pertimbangkan untuk mengaktifkan kompresi ROW atau PAGE karena terkadang dapat membantu. Tapi tolong lakukan penelitian terlebih dahulu karena ada beberapa situasi ketika mereka memiliki efek negatif. Ada dokumentasi di MSDN untuk membantu Anda mengetahuinya serta beberapa alat untuk membantu memperkirakan potensi penghematan. Tetapi bahkan jika Anda mengaktifkan kompresi, saya tidak akan melihat tindakan itu sebagai pengganti proyek yang Anda lakukan di sini.
  2. Tambahkan pemicu AFTER UPDATE, DELETE di [table] agar perubahan tetap sinkron (tetapi tidak perlu khawatir tentang baris baru)
  3. Buat Pekerjaan Agen SQL yang memindahkan baris yang hilang dalam kumpulan. Lakukan ini dalam satu lingkaran yang melakukan INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
  4. Klausa WHERE dan ORDER BY bergantung pada situasinya. Mereka harus diarahkan untuk memanfaatkan indeks berkerumun sebaik-baiknya. Jika indeks cluster dari tabel baru secara struktural sama dengan tabel lama/saat ini, maka pada awal setiap loop Anda bisa mendapatkan MAX([id]) dari [tableNew] dan menggunakannya untuk mendapatkan tabel WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id] .
  5. Buat tabel baru, pemicu pada tabel saat ini, dan SQL Agent Job seminggu atau lebih sebelum Anda perlu melakukan cut-over penuh. Kerangka waktu itu mungkin berubah berdasarkan situasi Anda, tetapi pastikan untuk memberi diri Anda banyak waktu. Jauh lebih baik bagi pekerjaan untuk menyelesaikan migrasi baris dan hanya memiliki sedikit tetesan dalam satu waktu daripada harus 100 ribu lebih malu dari set lengkap karena rilis seharusnya dimulai.
  6. Jika rencananya adalah untuk memigrasi tabel terkait lainnya (referensi PK untuk dua FK yang ingin Anda ubah menjadi INT s), lalu buat bidang tersebut di sini INT sekarang dan jangan tambahkan FK sampai tabel lain tersebut dimigrasikan untuk memiliki bidang INT sebagai PK mereka. Anda tidak ingin membangun kembali tabel ini hanya untuk membuat perubahan pada kolom FK.
  7. Selama cut-over (dalam TRY / CATCH, tentu saja):
    1. MULAI TRANS
    2. lakukan penghitungan baris terakhir pada kedua tabel untuk memastikan semuanya dipindahkan (mungkin ingin memeriksa kewarasan baris sebelum rilis untuk memastikan bahwa pemicu melakukan pembaruan dan penghapusan seperti yang diharapkan)
    3. ganti nama tabel saat ini menjadi "lama"
    4. ganti nama tabel "baru" menjadi tidak "baru"
    5. lepaskan tugas Agen SQL (atau setidaknya nonaktifkan)
    6. ganti nama dan objek dependen seperti batasan, dll
    7. KOMITMEN


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Koneksi Sql menunggu 15 detik meskipun batas waktu 3 detik dalam string koneksi

  2. Apakah mungkin menjalankan beberapa pernyataan DDL di dalam transaksi (dalam SQL Server)?

  3. Dapatkan nama pengguna yang masuk setiap hari dari basis data

  4. SQL Server AutoIncrement bervariasi berdasarkan nilai bidang lain

  5. Bagaimana menampilkan data dari database ke dalam kotak teks, dan memperbaruinya