Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Трябва ли да използвам вградена колона varchar(max) или да я съхранявам в отделна таблица?

Дръжте го на линия. Под кориците 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 вече са текстови указател в единицата за разпределение на LOB:

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)                    

За целите на завършването можем също така да премахнем едно от полетата без максимум от реда:

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 опцията постига същия резултат при безплатна цена за разработка/тест.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да промените настройките за конфигурация за поща на база данни в SQL Server (T-SQL)

  2. 7645 Нулев или празен предикат на пълен текст

  3. Как да генерирам произволно число за всеки ред в T-SQL избор?

  4. Обосновка за редовно обслужване на SQL сървър

  5. Не може да се свърже със SQL Server с PHP