Halten Sie es inline. Unter der Decke speichert SQL Server bereits seit SQL 2005 die MAX-Spalten in einer separaten 'Zuweisungseinheit'. Siehe Tabellen- und Indexorganisation. Dies ist im Endeffekt genau das Gleiche wie das Behalten der MAX-Spalte in ihrer eigenen Tabelle, aber ohne jeglichen Nachteil, dies explizit zu tun.
Eine explizite Tabelle zu haben, wäre eigentlich beides langsamer (aufgrund der Fremdschlüsseleinschränkung) und verbrauchen mehr Platz (wegen der DetaiID-Duplizierung). Ganz zu schweigen davon, dass mehr Code erforderlich ist und Fehler eingeführt werden, indem ... Code geschrieben wird.
Alternativtext http://i.msdn.microsoft.com/ms189051.3be61595-d405-4b30-9794-755842d7db7e(de-de,SQL.100).gif
Aktualisieren
Um den tatsächlichen Speicherort von Daten zu überprüfen, kann ein einfacher Test dies zeigen:
use tempdb;
go
create table a (
id int identity(1,1) not null primary key,
v_a varchar(8000),
nv_a nvarchar(4000),
m_a varchar(max),
nm_a nvarchar(max),
t text,
nt ntext);
go
insert into a (v_a, nv_a, m_a, nm_a, t, nt)
values ('v_a', N'nv_a', 'm_a', N'nm_a', 't', N'nt');
go
select %%physloc%%,* from a
go
Der %%physloc%%
Pseudo-Spalte zeigt die tatsächliche physische Position der Zeile an, in meinem Fall war es Seite 200:
dbcc traceon(3604)
dbcc page(2,1, 200, 3)
Slot 0 Column 2 Offset 0x19 Length 3 Length (physical) 3
v_a = v_a
Slot 0 Column 3 Offset 0x1c Length 8 Length (physical) 8
nv_a = nv_a
m_a = [BLOB Inline Data] Slot 0 Column 4 Offset 0x24 Length 3 Length (physical) 3
m_a = 0x6d5f61
nm_a = [BLOB Inline Data] Slot 0 Column 5 Offset 0x27 Length 8 Length (physical) 8
nm_a = 0x6e006d005f006100
t = [Textpointer] Slot 0 Column 6 Offset 0x2f Length 16 Length (physical) 16
TextTimeStamp = 131137536 RowId = (1:182:0)
nt = [Textpointer] Slot 0 Column 7 Offset 0x3f Length 16 Length (physical) 16
TextTimeStamp = 131203072 RowId = (1:182:1)
Alle Spaltenwerte außer TEXT und NTEXT wurden inline gespeichert, einschließlich der MAX-Typen.
Nach dem Ändern der Tabellenoptionen und dem Einfügen einer neuen Zeile (sp_tableoption wirkt sich nicht auf vorhandene Zeilen aus) wurden die MAX-Typen in ihren eigenen Speicher verdrängt:
sp_tableoption 'a' , 'large value types out of row', '1';
insert into a (v_a, nv_a, m_a, nm_a, t, nt)
values ('2v_a', N'2nv_a', '2m_a', N'2nm_a', '2t', N'2nt');
dbcc page(2,1, 200, 3);
Beachten Sie, dass die Spalten m_a und nm_a jetzt ein Textzeiger in die LOB-Zuweisungseinheit sind:
Slot 1 Column 2 Offset 0x19 Length 4 Length (physical) 4
v_a = 2v_a
Slot 1 Column 3 Offset 0x1d Length 10 Length (physical) 10
nv_a = 2nv_a
m_a = [Textpointer] Slot 1 Column 4 Offset 0x27 Length 16 Length (physical) 16
TextTimeStamp = 131268608 RowId = (1:182:2)
nm_a = [Textpointer] Slot 1 Column 5 Offset 0x37 Length 16 Length (physical) 16
TextTimeStamp = 131334144 RowId = (1:182:3)
t = [Textpointer] Slot 1 Column 6 Offset 0x47 Length 16 Length (physical) 16
TextTimeStamp = 131399680 RowId = (1:182:4)
nt = [Textpointer] Slot 1 Column 7 Offset 0x57 Length 16 Length (physical) 16
TextTimeStamp = 131465216 RowId = (1:182:5)
Der Vollständigkeit halber können wir auch eines der Nicht-Max-Felder aus der Reihe zwingen:
update a set v_a = replicate('X', 8000);
dbcc page(2,1, 200, 3);
Beachten Sie, wie die v_a-Spalte im Row-Overflow-Speicher gespeichert wird:
Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4
v_a = [BLOB Inline Root] Slot 0 Column 2 Offset 0x19 Length 24 Length (physical) 24
Level = 0 Unused = 99 UpdateSeq = 1
TimeStamp = 1098383360
Link 0
Size = 8000 RowId = (1:176:0)
Wie andere bereits kommentiert haben, werden die MAX-Typen standardmäßig inline gespeichert, wenn sie passen. Für viele DW-Projekte wäre dies nicht akzeptabel, da die typischen DW-Ladevorgänge scannen oder zumindest einen Bereichsscan durchführen müssen, also die sp_tableoption ..., 'large value types out of row', '1'
sollte benutzt werden. Beachten Sie, dass dies keine Auswirkungen auf vorhandene Zeilen hat, in meinem Test nicht einmal beim Indexneuaufbau , daher muss die Option frühzeitig aktiviert werden.
Für die meisten OLTP-Type-Loads ist es aber eigentlich von Vorteil, dass MAX-Types möglichst inline gespeichert werden, da das OLTP-Zugriffsmuster zu suchen ist und die Zeilenbreite darauf kaum Einfluss hat.
Trotzdem zur ursprünglichen Frage:Eine separate Tabelle ist nicht erforderlich. Aktivieren der large value types out of row
Option erzielt das gleiche Ergebnis bei kostenlosen Entwicklungs-/Testkosten.