sql >> Database teknologi >  >> RDS >> Sqlserver

Skal jeg bruge en inline varchar(max) kolonne eller gemme den i en separat tabel?

Hold det inline. Under dækslerne gemmer SQL Server allerede MAX-kolonnerne i en separat 'allokeringsenhed' siden SQL 2005. Se Tabel og Indeks Organisation. Dette er faktisk nøjagtigt det samme som at beholde MAX-kolonnen i sin egen tabel, men uden nogen ulempe ved eksplicit at gøre det.

At have en eksplicit tabel ville faktisk være både langsommere (på grund af den fremmede nøgle-begrænsning) og forbruge mere plads (på grund af DetaiID-duplikationen). For ikke at nævne, at det kræver mere kode, og fejl introduceres ved... at skrive kode.

alt tekst http://i.msdn.microsoft.com/ms189051.3be61595-d405-4b30-9794-755842d7db7e(en-us,SQL.100).gif

Opdater

For at kontrollere den faktiske placering af data kan en simpel test vise 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%% pseudo-kolonnen viser den faktiske fysiske placering af rækken, i mit tilfælde var det side 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 kolonneværdier undtagen TEXT og NTEXT blev gemt inline, inklusive MAX-typerne.
Efter at have ændret tabelindstillingerne og indsat en ny række (sp_tableoption påvirker ikke eksisterende rækker), blev MAX-typerne smidt ud i deres eget lager:

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);

Bemærk, hvordan m_a og nm_a kolonner nu er en Textpointer i LOB allokeringsenheden:

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)                    

For fuldførelsens skyld kan vi også tvinge det ene af de ikke-maks. felter ud af rækken:

update a set v_a = replicate('X', 8000);
dbcc page(2,1, 200, 3);

Bemærk, hvordan v_a-kolonnen gemmes i Row-Overflow-lageret:

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 andre allerede har kommenteret, er MAX-typerne gemt inline som standard, hvis de passer. For mange DW-projekter ville dette være uacceptabelt, fordi de typiske DW-belastninger skal scanne eller i det mindste rækkeviddescanne, så sp_tableoption ..., 'large value types out of row', '1' skal bruges. Bemærk, at dette ikke påvirker eksisterende rækker, i min test ikke engang ved indeksgenopbygning , så muligheden skal aktiveres tidligt.

For de fleste indlæsninger af OLTP-typen er det faktisk en fordel, at MAX-typer er gemt inline, hvis det er muligt, da OLTP-adgangsmønsteret er at søge, og rækkebredden har ringe indflydelse på det.

Ikke desto mindre med hensyn til det oprindelige spørgsmål:separat tabel er ikke nødvendig. Aktivering af large value types out of row option opnår det samme resultat til en gratis pris for udvikling/test.



  1. Hvordan angiver jeg en unik begrænsning for flere kolonner i MySQL?

  2. Gendan SQL-database nemt – Trin-for-trin-vejledning

  3. PostgreSQL høj tilgængelighed med Master-Slave &Master-Master-arkitekturer

  4. Forespørg to tabeller fra forskellige skemaer