Ich muss eine breite denormalisierte Tabelle mit vielen Dezimalspalten (26,8) erstellen (weniger als 1024 Spalten, die meisten Spalten wären null oder null). Ich kenne ungefähr 8060 Bytes pro Zeilenbeschränkung, also habe ich versucht, eine Tabelle mit Seitenkomprimierung zu erstellen. Der folgende Code erstellt eine Tabelle, fügt eine Zeile ein und fragt die Zeilengröße ab. Die Zeilengröße liegt weit unter dem Grenzwert, aber wenn ich versuche, der Tabelle eine weitere Dezimalspalte (26,8) hinzuzufügen, schlägt der Vorgang mit dem Fehler fehl. "Das Erstellen oder Ändern der Tabelle 't1' ist fehlgeschlagen, da die minimale Zeilengröße 8074 einschließlich 1256 betragen würde Bytes interner Overhead. ". Gibt es eine Möglichkeit, eine einzelne Tabelle mit so vielen Spalten zu erstellen?
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
Felder in eine Tabelle bekommen, ohne Seitenkomprimierung oder Dezimalkomprimierung. Wenn Sie die vardezimale, aber nicht die Seitenkomprimierung aktivieren, springt der Overhead auf über 1 K. Es besteht die Möglichkeit, dass Sie abhängig von Ihren Werten mehr Felder pro Seite ohne vardezimal speichern können.Antworten:
Das Limit, auf das Sie stoßen, hat nichts mit den auf der Seite gespeicherten Daten zu tun. Die Berechnung erfolgt anhand der Datentypen der Spalten. Aus diesem Grund tritt der Fehler ohne Daten in der Tabelle auf. Die Komprimierung verschlimmert diese Grenze. Sie können hinter dem Overhead über die technischen Details lesen Sie hier .
Sie können dieses Problem mithilfe von SPARSE- Spalten umgehen . Das bedeutet, dass Einfügungen je nach dem, was Sie einfügen, möglicherweise fehlschlagen. Sie können jedoch das 8060-Byte-Limit umgehen. Der folgende Code zeigt, dass Sie problemlos 1023 Spalten erstellen können:
Aufgrund aller Einschränkungen (lesen Sie den verlinkten Artikel) ist dies möglicherweise nicht für Ihren Anwendungsfall geeignet. Insbesondere werden nur
NULL
Werte (nicht0
) so optimiert, dass sie sehr wenig Platz beanspruchen. Wenn Sie versuchen, zu viele0
s in eine einzelne Zeile einzufügen , wird eine Fehlermeldung angezeigt. Folgendes sehe ich, wenn ich versuche, 10230
Werte einzufügen :Ich nehme an, wenn Sie wirklich verzweifelt sind, können Sie die Spalten
VARCHAR(27)
stattdessen so erstellen . Spalten mit variabler Länge können von der Seite verschoben werden, sodass Sie die 8060-Byte-Grenze in der Tabellendefinition überschreiten können. Das Einfügen bestimmter Wertekombinationen schlägt jedoch fehl. SQL Server warnt Sie beim Erstellen der Tabelle davor:Die Seiten- oder Zeilenkomprimierung kann hilfreich sein, wenn Sie sich für den
VARCHAR(27)
Ansatz entscheiden. Dadurch wird der von0
undNULL
. Mit kannVARCHAR(27)
ich 10230
Werte ganz gut einfügen .quelle
Abgesehen von den technischen Aspekten und der vorgeschlagenen Problemumgehung (unter Verwendung von
VARCHAR(27)
Spalten), die in @ Joes Antwort erörtert wurden , stelle ich die " Notwendigkeit , eine [breite] denormalisierte Tabelle zu erstellen " in Frage, wie sie vom OP ausgedrückt wird, es sei denn, es gibt eine merkwürdige technische Anforderung, dass alle diese Spalten muss in einer einzigen Tabelle sein, ich würde vorschlagen / empfehlen, sie auf so viele "Geschwister" -Tische wie nötig zu verteilen. Geschwistertabellen sind Tabellen, die:IDENTITY
Spalte (und keine FK zu den anderen)IDENTITY
Hier teilen Sie die logische Zeile auf zwei oder mehr physische Tabellen auf. Aber das ist im Wesentlichen das, was Normalisierung sowieso ist und wofür relationale Datenbanken ausgelegt sind.
In diesem Szenario entsteht durch das Duplizieren der PK zusätzlicher Speicherplatz und zusätzliche Abfragekomplexität, da entweder
INNER JOIN
die Tabellen zusammen verwendet werden müssen (häufig, aber nicht immer, es sei denn, alleSELECT
Abfragen verwenden alle Spalten, dies geschieht jedoch normalerweise nicht). oder erstellen Sie eine explizite Transaktion zuINSERT
oderUPDATE
zusammen (DELETE
kann überON DELETE CASCADE
set auf dem FK abgewickelt werden ).Sie erhalten jedoch die Vorteile eines ordnungsgemäßen Datenmodells mit geeigneten nativen Datentypen und ohne Tricks, die später unvorhergesehene Folgen haben könnten. Selbst wenn die Verwendung
VARCHAR(27)
dies auf technischer Ebene ermöglicht, denke ich pragmatisch nicht, dass das Speichern von Dezimalstellen als Zeichenfolgen im besten Interesse Ihres / des Projekts liegt.Wenn Sie also nur eine einzelne Tabelle "benötigen", weil Sie nicht wissen, dass eine einzelne logische Entität nicht physisch in einem einzelnen Container dargestellt werden muss, versuchen Sie nicht, all dies in eine einzelne Tabelle zu zwingen, wenn dies funktioniert elegant über mehrere Tabellen.
Das folgende Beispiel veranschaulicht das Grundkonzept:
INSTALLIEREN
PRÜFUNG
Kehrt zurück:
quelle