Strukturering av datasidor i SQL Server 6.5
Strukturering av datasidor i SQL Server 6.5
av Alexander Chigrik
Det finns fem olika sidor i MS SQL 6.5:
- Datasidor
- Indexsidor
- Allokeringssidor
- Text/Bildsidor
- Distrubutionssidor
Storleken på datasidorna i MS SQL 6.5 ligger på 2 kB (2 048 bytes). Varje datasida består av följande tre delar:
- 32-bitar Header
- Datarader
- Offsettabell
Se figur 1:
(Figur 1: Generell struktur inom datasidorna)
Här följer de olika delarna i sidheadern:
pageno: Ett logiskt sidnummer
nextpg: Nästa logiska sidnummer
prevpg: Det förra logiska sidnumret
objID: Tabellens ID
timestamp: Intern identifierare
nextrno: Nästa radnummer som kommer att skrivas på sidan
level: Indexnivån
indID: Indexets ID
freeoff: Pekare till det lediga utrymmet längs ned på sidan
minlen: Minsta längden på rader för den här datasidan
Offsettabellen innehåller två bytes av varje rad på datasidan. MS SQL Server 6.5 använder offsettabellen till att ta reda på en rads adress. Varje cell i offsettabellen innehåller adressen till raden på datasidan.
När du lägger in ett nytt record, så scannar MS SQL Server 6.5 igenom offsettabellen från slutet. När den finner en cell med ett noll-värde, så lägger den in offset-värdet för den nya raden i den cellen. Om den inte finner någon cell med ett noll-värde så skapar den en ny rad i offsettabellen, skriver ett nytt värde till ”freeoff” fältet i sidheadern samt ökar värdet i ”nextrno” fältet i sidheadern med 1.
När du raderar ett record så skriver MS SQL Server 6.5 över värdet i den korrekta cellen med ett noll-värde, raderar raden, flyttar om de övriga raderna för att förhindra tomma utrymmen samt sätter ett nytt värde till ”freeoff” fältet i sidheadern. Alla rader lagras kontinuerligt på datasidan.
Följande kommando kan du använda då du vill se en datasidan struktur (kommandot är inte särskilt väl dokumenterat på MS SQL Server 6.5 Books Online).
DBCC PAGE ({dbid|dbname}, pagenum [,print option] [,cache] [,logical])
där:
dbID | dbName: Skriv antingen in databasens ID eller databasens namn.
Pagenum: Skriv in sidnumret på den SQL Serversidan som ska analyseras.
Print Option: (Tillval) Här kan du sätta värdena 0, 1 eller 2.
0 (standard) – Alternativet får DBCC PAGE att endast skriva ut information om sidheadern.
1 – Det här alternativet får DBCC PAGE att skriva ut informationen om Sidheadern, varje rad av information på sidan samt sidans offsettabell. Varje rad som skrivs ut kommer att separeras från varandra.
2 – Det här alternativet är precis som det första (1), förutom att det skriver ut alla rader som en helhet hellre än att skriva ut varje rad individuellt. Balansen och headern kommer också att visas upp.
cache – (Tillval) Den här parametern tillåter antingen en 1 eller en 0
0 – Det här alternativet får DBCC PAGE att hämta sidnumret från hårddisken hellre än att leta efter det i cachen.
1 – (Standard) Om sidnumret finns i cachen så hämtar det här alternativet hellre sidnumret därifrån, än från bara hårddisken.
logical – (Tillval) Det här parametern är användbar ifall sidnumret som ska hämtas är en virtuell sida istället för en logisk sida. Det kan vara antingen 0 eller 1.
0 – Används om sidan som ska hämtas har ett virtuellt sidnummer.
1 – (Standard) Används om sidan som ska hämtas har ett logiskt sidnummer.
I alla kommande exempel så har jag använt mig av Trace flaggan 3604, för att bättre kunna illustrera vad som händer i exemplen. Trace flaggan 3604 skickar tillbaka en Traceoutput till klienten. Den här Trace flaggan används endast då du sätter Trace flaggor med DBCC TRACEON eller DBCC TRACEOFF.
Undersök datasidans struktur
I det här exemplet ska vi ta ut en datasida från ”discounts” tabellen i PUBSdatabasen. Använd följande kod:
USE pubs
GO
DBCC TRACEON (3604)
GO
DECLARE @pgid int
SELECT @pgid = first FROM sysindexes WHERE id = object_id('discounts')
DBCC PAGE (pubs, @pgid, 1)
GO
Min dator ger mig följande resultat:
PAGE:
Page found in cache.
BUFFER:
Buffer header for buffer 0xf96580
page=0x1181000 bdnew=0xf96580 bdold=0xf96580 bhash=0x0
bnew=0xf964c0
bold=0xf96640 bvirtpg=2540 bdbid=5 bpinproc=0 bkeep=0 bspid=0
bstat=0x1004 bpageno=488
PAGE HEADER:
Page header for page 0x1181000
pageno=488 nextpg=0 prevpg=0 objid=544004969 timestamp=0001 0000486a
nextrno=3 level=0 indid=0 freeoff=122 minlen=5
page status bits: 0x100,0x1
DATA:
Offset 32 –
01181020: 0100017e 041a0049 6e697469 616c2043 ...~...Initial C
01181030: 7573746f 6d657202 1707 ustomer...
Offset 58 –
0118103a: 0401019e 02200056 6f6c756d 65204469 ..... .Volume Di
0118104a: 73636f75 6e746400 e803051a 18161607 scountd.........
Offset 90 –
0118105a: 020201f4 01200043 7573746f 6d657220 ..... .Customer
0118106a: 44697363 6f756e74 38303432 031c1807 Discount8042....
OFFSET TABLE:
Row – Offset
2 (0x2) - 90 (0x5a), 1 (0x1) - 58 (0x3a),
0 (0x0) - 32 (0x20),
Se figur 2:
(Figur 2: Discounts-tabellens struktur för datasidan)
Ett exempel på en datasida efter att ha raderat ett record
När du raderar ett record så skriver MS SQL Server 6.5 över värdet i den korrekta cellen med ett noll-värde, raderar raden, flyttar om de övriga raderna för att förhindra tomma utrymmen samt sätter ett nytt värde till ”freeoff” fältet i sidheadern. Alla rader lagras kontinuerligt på datasidan.
DELETE FROM discounts WHERE discounttype = 'Volume Discount'
Jag får följande resultat på min dator:
PAGE:
Page found in cache.
BUFFER:
Buffer header for buffer 0xf96580
page=0x1181000 bdnew=0xf5a448 bdold=0xf5a448 bhash=0x0
bnew=0xf964c0
bold=0xf96640 bvirtpg=2540 bdbid=5 bpinproc=7 bkeep=0 bspid=0
bstat=0x1004 bpageno=488
PAGE HEADER:
Page header for page 0x1181000
pageno=488 nextpg=0 prevpg=0 objid=544004969 timestamp=0001 0000519c
nextrno=3 level=0 indid=0 freeoff=90 minlen=5
page status bits: 0x100,0x10,0x1
DATA:
Offset 32 –
01181020: 0100017e 041a0049 6e697469 616c2043 ...~...Initial C
01181030: 7573746f 6d657202 1707 ustomer...
Offset 58 –
0118103a: 020201f4 01200043 7573746f 6d657220 ..... .Customer
0118104a: 44697363 6f756e74 38303432 031c1807 Discount8042....
OFFSET TABLE:
Row – Offset
2 (0x2) - 58 (0x3a), 1 (0x1) - 0 (0x0),
0 (0x0) - 32 (0x20),
Se figur 3:
(Figur 3: Efter att du har raderat)
Ett exempel på hur du lägger in värden på en datasida
När du lägger in ett nytt record, så scannar MS SQL Server 6.5 igenom offsettabellen från slutet. När den finner en cell med ett noll-värde, så lägger den in offset-värdet för den nya raden i den cellen. Om den inte finner någon cell med ett noll-värde så skapar den en ny rad i offsettabellen, skriver ett nytt värde till ”freeoff” fältet i sidheadern samt ökar värdet i ”nextrno” fältet i sidheadern med 1.
INSERT discounts values('Volume Discount', NULL, 100, 1000, 6.7)
Det här är resultatet från min dator:
PAGE:
Page found in cache.
BUFFER:
Buffer header for buffer 0xf96580
page=0x1181000 bdnew=0xf5a448 bdold=0xf5a448 bhash=0x0
bnew=0xf964c0
bold=0xf96640 bvirtpg=2540 bdbid=5 bpinproc=8 bkeep=0 bspid=0
bstat=0x1004 bpageno=488
PAGE HEADER:
Page header for page 0x1181000
pageno=488 nextpg=0 prevpg=0 objid=544004969 timestamp=0001 0000519e
nextrno=3 level=0 indid=0 freeoff=122 minlen=5
page status bits: 0x100,0x10,0x1
DATA:
Offset 32 –
01181020: 0100017e 041a0049 6e697469 616c2043 ...~...Initial C
01181030: 7573746f 6d657202 1707 ustomer...
Offset 58 –
0118103a: 020201f4 01200043 7573746f 6d657220 ..... .Customer
0118104a: 44697363 6f756e74 38303432 031c1807 Discount8042....
Offset 90 –
0118105a: 0401019e 02200056 6f6c756d 65204469 ..... .Volume Di
0118106a: 73636f75 6e746400 e803051a 18161607 scountd.........
OFFSET TABLE:
Row – Offset
2 (0x2) - 58 (0x3a), 1 (0x1) - 90 (0x5a),
0 (0x0) - 32 (0x20),
Se figur 4:
(Figur 4: Efter att du har lagt in värden)
Att lära sig hur dina data struktureras i en databas, kan förbättra din förståelse för hur SQL Server verkligen fungerar. Ju mer du vet om den underliggande arkitekturen, desto bättre kan du förstå hur du kan höja din SQL Servers databasprestanda.
0 Kommentarer