Håll det inline. Under täcket lagrar SQL Server redan MAX-kolumnerna i en separat 'allokeringsenhet' sedan SQL 2005. Se Tabell- och Indexorganisation. Detta är i själva verket exakt samma sak som att behålla MAX-kolumnen i sin egen tabell, men utan någon nackdel med att uttryckligen göra det.
Att ha en explicit tabell skulle faktiskt vara både långsammare (på grund av den främmande nyckeln) och konsumera mer utrymme (på grund av DetaiID-dupliceringen). För att inte tala om att det kräver mer kod, och buggar introduceras genom att... skriva kod.
alt text http://i.msdn.microsoft.com/ms189051.3be61595-d405-4b30-9794-755842d7db7e(en-us,SQL.100).gif
Uppdatera
För att kontrollera den faktiska platsen för data kan ett enkelt test visa det:
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
%%physloc%%
pseudokolumnen visar den faktiska fysiska platsen för raden, i mitt fall var det sidan 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)
Alla kolumnvärden utom TEXT och NTEXT lagrades inline, inklusive MAX-typerna.
Efter att ha ändrat tabellalternativen och infogat en ny rad (sp_tableoption påverkar inte befintliga rader), vräktes MAX-typerna till sin egen lagring:
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);
Notera hur kolumnerna m_a och nm_a nu är en textpekare i LOB-tilldelningsenheten:
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)
För kompletteringens skull kan vi också tvinga det ena av de icke-maxfält ut ur rad:
update a set v_a = replicate('X', 8000);
dbcc page(2,1, 200, 3);
Notera hur v_a-kolumnen lagras i Row-Overflow-lagringen:
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)
Så, som andra redan har kommenterat, lagras MAX-typerna inline som standard, om de passar. För många DW-projekt skulle detta vara oacceptabelt eftersom de typiska DW-belastningarna måste skanna eller åtminstone intervallskanning, så sp_tableoption ..., 'large value types out of row', '1'
borde användas. Observera att detta inte påverkar befintliga rader, i mitt test inte ens vid ombyggnad av index , så alternativet måste aktiveras tidigt.
För de flesta belastningar av OLTP-typ är dock det faktum att MAX-typer lagras inline om möjligt faktiskt en fördel, eftersom OLTP-åtkomstmönstret är att söka och radbredden har liten inverkan på det.
Icke desto mindre när det gäller den ursprungliga frågan:separat tabell är inte nödvändig. Aktivera large value types out of row
option uppnår samma resultat till en gratis kostnad för utveckling/test.