Держите это встроенным. Под крышками SQL Server уже хранит столбцы MAX в отдельной «единице выделения» начиная с SQL 2005. См. Организация таблиц и индексов . По сути, это то же самое, что и сохранение столбца MAX в отдельной таблице, но без каких-либо недостатков явного выполнения этого.
Наличие явной таблицы на самом деле будет медленнее (из-за ограничения внешнего ключа) и потребляет больше места (из-за дублирования DetaiID). Не говоря уже о том, что для этого требуется больше кода, а ошибки появляются в результате ... написания кода.
альтернативный текст http://i.msdn.microsoft.com/ms189051.3be61595-d405-4b30-9794-755842d7db7e(en-us,SQL.100).gif
Обновление
Чтобы проверить фактическое местоположение данных, простой тест может показать это:
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%%
будет показано фактическое физическое местоположение строки, в моем случае это была страница 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)
Все значения столбцов, кроме TEXT и NTEXT, были сохранены встроенными, включая типы MAX.
После изменения параметров таблицы и вставки новой строки (sp_tableoption не влияет на существующие строки) типы MAX были удалены в их собственное хранилище:
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);
Обратите внимание, что столбцы m_a и nm_a теперь являются текстовыми указателями в блоке выделения больших объектов:
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)
Для завершенности мы также можем принудительно вывести одно из полей не max из строки:
update a set v_a = replicate('X', 8000);
dbcc page(2,1, 200, 3);
Обратите внимание, как столбец v_a хранится в хранилище с переполнением строк:
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)
Таким образом, как уже отмечали другие, типы MAX по умолчанию сохраняются встроенными, если они подходят. Для многих проектов DW это было бы неприемлемо, потому что типичные нагрузки DW должны сканировать или, по крайней мере, сканировать по дальности, поэтому следует использовать sp_tableoption ..., 'large value types out of row', '1'
. Обратите внимание, что это не влияет на существующие строки, в моем тесте даже на перестроение индекса , поэтому эту опцию нужно включить раньше.
Для большинства нагрузок типа OLTP, хотя тот факт, что типы MAX хранятся в строке, если это возможно, на самом деле является преимуществом, поскольку шаблон доступа OLTP должен искать, а ширина строки оказывает на него незначительное влияние.
Тем не менее, относительно исходного вопроса: отдельная таблица не нужна. Включение опции large value types out of row
дает тот же результат при бесплатной стоимости разработки / тестирования.