Saya perlu membuat tabel denormalized luas dengan banyak desimal (26,8) kolom (kurang dari 1024 batas kolom, sebagian besar kolom akan menjadi nol atau nol). Saya tahu tentang 8060 byte per batasan baris, jadi saya mencoba membuat tabel dengan kompresi halaman. Kode di bawah ini membuat tabel, memasukkan satu baris dan menanyakan ukuran baris. Ukuran baris jauh di bawah batas, tetapi jika saya mencoba menambahkan satu lagi desimal (26,8) kolom ke tabel, operasi gagal dengan kesalahan "Membuat atau mengubah tabel 't1' gagal karena ukuran baris minimum adalah 8074, termasuk 1256 byte dari overhead internal. " Apakah ada cara untuk membuat tabel tunggal dengan banyak kolom?
drop table t1
GO
create table t1(c1 decimal(26, 8) null)
with (data_compression = page)
GO
declare @i int = 2;
declare @sql varchar(100);
while @i <= 486
begin
set @sql = 'alter table t1 add c' + convert(varchar, @i) + ' decimal(26, 8) null';
execute (@sql);
set @i += 1;
end;
GO
insert into t1(c1) select 0
GO
declare @i int = 2;
declare @sql varchar(100);
while @i <= 486
begin
set @sql = 'update t1 set c' + convert(varchar, @i) + ' = 0';
execute (@sql);
set @i += 1;
end;
GO
select max_record_size_in_bytes from sys.dm_db_index_physical_stats (db_id(), object_id('t1'), NULL, NULL, 'DETAILED')
GO
DECIMAL(26, 8) NULL
bidang ke dalam tabel, tanpa kompresi halaman atau kompresi desimal. Mengaktifkan kompresi vardecimal tetapi tidak halaman, overhead melompat ke lebih dari 1 K. Ada kemungkinan di luar bahwa Anda akan dapat menyimpan lebih banyak bidang per halaman tanpa vardecimal, tergantung pada nilai Anda.Jawaban:
Batas yang Anda temui tidak ada hubungannya dengan data yang disimpan di halaman. Perhitungan dilakukan berdasarkan tipe data kolom. Itu sebabnya Anda mengalami kesalahan tanpa data di tabel. Kompresi membuat batas ini semakin buruk. Anda dapat membaca tentang detail teknis di balik overhead di sini .
Anda dapat mengatasi masalah ini dengan menggunakan kolom SPARSE . Itu berarti bahwa kemungkinan insert gagal tergantung pada apa yang Anda masukkan, tetapi Anda dapat melewati batas 8060 byte. Kode berikut menunjukkan bahwa Anda dapat membuat 1023 kolom dengan baik:
Namun, semua batasan di sekitarnya (baca artikel yang ditautkan) mungkin membuat ini tidak cocok untuk kasus penggunaan Anda. Secara khusus, hanya
NULL
nilai-nilai (tidak0
) yang dioptimalkan untuk mengambil ruang yang sangat sedikit. Jika Anda mencoba memasukkan terlalu banyak0
dalam satu baris, Anda akan mendapatkan kesalahan. Inilah yang saya lihat ketika saya mencoba memasukkan0
nilai 1023 :Saya kira jika Anda benar-benar putus asa, Anda dapat membuat kolom sebagai
VARCHAR(27)
gantinya. Kolom panjang variabel dapat dipindahkan dari halaman sehingga Anda dapat melebihi batas 8060 byte dalam definisi tabel tetapi memasukkan kombinasi nilai tertentu akan gagal. SQL Server memperingatkan Anda tentang hal ini ketika membuat tabel:Kompresi halaman atau baris dapat membantu jika Anda menggunakan
VARCHAR(27)
pendekatan tersebut. Itu akan meminimalkan ruang yang digunakan oleh keduanya0
danNULL
. DenganVARCHAR(27)
saya dapat memasukkan 10230
nilai dengan baik.sumber
Di luar aspek teknis dan usulan penyelesaian (menggunakan
VARCHAR(27)
kolom) yang dibahas dalam jawaban @ Joe , saya mempertanyakan " kebutuhan untuk membuat tabel denormalized luas" sebagaimana diungkapkan oleh OP Kecuali jika ada beberapa persyaratan teknis aneh bahwa semua kolom ini harus dalam satu tabel, saya akan menyarankan / merekomendasikan menyebar mereka di banyak "saudara" tabel yang diperlukan. Tabel saudara adalah tabel yang:IDENTITY
kolom (dan tidak ada FK ke yang lain)IDENTITY
Di sini Anda membelah baris logis di dua atau lebih tabel fisik. Tapi itu pada dasarnya apa itu normalisasi, dan database relasional apa yang dirancang untuk ditangani.
Dalam skenario ini Anda mengeluarkan beberapa ruang tambahan yang digunakan dengan menduplikasi PK, dan beberapa kompleksitas kueri tambahan karena kebutuhan untuk
INNER JOIN
tabel bersama (sering tetapi tidak selalu, kecuali jika semuaSELECT
kueri menggunakan semua kolom, tapi itu biasanya tidak terjadi) atau membuat Transaksi eksplisit untukINSERT
atauUPDATE
mereka bersama-sama (DELETE
dapat ditangani melaluiON DELETE CASCADE
set di FK).NAMUN, Anda mendapatkan manfaat dari memiliki model data yang tepat dengan tipe data asli yang tepat, dan tidak ada tipu daya yang dapat memiliki konsekuensi yang tidak terduga nantinya. Bahkan jika menggunakan
VARCHAR(27)
memungkinkan ini bekerja pada tingkat teknis, secara pragmatis saya tidak berpikir menyimpan desimal karena string adalah untuk kepentingan terbaik Anda / proyek.Jadi, jika Anda hanya "membutuhkan" satu tabel karena tidak menyadari bahwa satu entitas logis tidak perlu diwakili secara fisik dalam satu wadah, maka jangan mencoba untuk memaksa semua ini menjadi satu tabel ketika itu akan bekerja anggun di beberapa tabel.
Contoh di bawah menggambarkan konsep dasar:
MENDIRIKAN
UJI
Pengembalian:
sumber