piątek, 31 grudnia 2010

%%rowdump%%

Następną funkcją dostarczającą nam pseudokolumny jest %%rowdump%%

SELECT %%rowdump%%,* FROM test
-------------



Znowu z pomocą przychodzi nam funkcja sys.fn_PhysLocFormatter

SELECT sys.fn_PhysLocFormatter(%%rowdump%%), * FROM test
-------------
                   id          tekst     dtekst               data
------------------ ----------- ----------------------------------------------------
(0:17104896:256)   1           abc       ABCqazwsx0987qa<..>  2010-12-30 13:41:44.673
(0:17104896:256)   2           abc       ABCqazwsx0987qa<..>  2010-12-30 13:44:31.423

Ciekawszych informacji dostarcza nam funkcja tabelaryczna sys.fn_RowDumpCracker

SELECT *
FROM test
CROSS APPLY sys.fn_RowDumpCracker(%%rowdump%%)s
WHERE id =1



Zwraca wyniki dla każdego wiersza typu varchar i nvarchar, jeżeli wartość pola mieści się na jednej stronie to IsInrow jest równe 1 a wartość InRowLength pokazuje ilość znaków, jeżeli serwer stworzy marker do innej strony IsInrow ma wartość 0 a długość pola wynosi zawsze 24.
Jeżeli użyjemy w tabeli pola typu sparse znacznik IsSparse zmieni się na 1 i funkcja zwróci również pola innego typu

czwartek, 30 grudnia 2010

%%lockres%%

Następną ciekawą funkcją dostępną w SQL Server 2005 i 2008 jest %%lockres%%
Pokazuje nam ona w pseudokolumnie klucz każdego rekordu (KeyHashValue)

SELECT %%lockres%%,* FROM test
-------------
                   id          tekst     dtekst               data
------------------ ----------- ----------------------------------------------------
(8194443284a0)     1           abc       ABCqazwsx0987qa<..>  2010-12-30 13:41:44.673
(61a06abd401c)     2           abc       ABCqazwsx0987qa<..>  2010-12-30 13:44:31.423

To ten magiczny znacznik widzimy w widoku sys.dm_tran_locks w polu resource_description dla typu key, to nim serwer posługuje się przy obsłudze lokowań

W innej sesji odpalamy

BEGIN TRAN
UPDATE test
SET tekst ='abcd'
WHERE id =1

I sprawdzamy
select * from sys.dm_tran_locks                     



Dzięki takiemu mechanizmowi możemy sprawdzać jakie wiersze są w zablokowane

SELECT a.* FROM test  AS a with (NOLOCK)
JOIN sys.dm_tran_locks AS l
ON a.%%lockres%% = l.resource_description
WHERE l.resource_type = 'KEY'     

-------------
id          tekst     dtekst               data
------------ ----------------------------------------------------
1           abc       ABCqazwsx0987qa<..>  2010-12-30 13:41:44.673


Wartość ta jest przechowywana na poziomie strony

DBCC PAGE (5, 1,20636,3) WITH TABLERESULTS, NO_INFOMSGS



Klucz jest generowany losowo i w tabeli o bardzo dużej ilości danych może się zdarzyc, że klucze się powtórzą, dochodzi wówczas do zablokowania rekordów zupełnie ze sobą niezwiązanych

select %%lockres%% FROM CalkiemSporaTabela --100 mln rekordow
group by %%lockres%%
having count(%%lockres%%)>1

------------
(06006b69f9b0)
.....
.....

(1485 row(s) affected)

%%physloc%%

W SQL Server 2008 pojawiła się bardzo ciekawa funkcja %%physloc%% dzięki niej możemy w pseudokolumnie zobaczyć adres fizyczny rekordu.

Robimy sobie poligon

CREATE  TABLE test ( id INT IDENTITY (1,1) PRIMARY KEY,
                             tekst VARCHAR(100),
                             dtekst VARCHAR(MAX),
                             data DATETIME)
go

INSERT test(tekst,dtekst,data)
VALUES
('abc','ABC',GETDATE())
go

SELECT %%physloc%%, * FROM test

--------------

                   id          tekst     dtekst               data
------------------ ----------- ----------------------------------------------------
0x9C50000001000000 1           abc       ABC                  2010-12-30 13:41:44.673


Dostajemy zahaszowany adres strony, można go rozwiązać przy pomocy funkcji skalarnej sys.fn_PhysLocFormatter lub funkcji tabelarycznej sys.fn_PhysLocCracker

SELECT sys.fn_PhysLocFormatter(%%physloc%%), * FROM test

--------------

                   id          tekst     dtekst               data
------------------ ----------- ----------------------------------------------------
(1:20636:0)        1           abc       ABC                  2010-12-30 13:41:44.673

Sprawdzamy

select  OBJECT_ID('test'), DB_ID()

           
----------- ------
2139154666  5
DBCC IND (5,2139154666,0)WITH TABLERESULTS, NO_INFOMSGS



Zgadza się,  co będzie jak zwiększymy rozmiar pola

UPDATE test
SET dtekst =dtekst +REPLICATE('qazwsx0987',20000)

Spodziewamy się, że pole dtekst będzie miało 200003 znaki ?

SELECT LEN(dtekst) FROM test

---------------
8003
Taka mała niespodzianka z polem max, ale nie o to nam chodzi

SELECT sys.fn_PhysLocFormatter(%%physloc%%), * FROM test

--------------

                   id          tekst     dtekst               data
------------------ ----------- ----------------------------------------------------
(1:20636:0)        1           abc       ABCqazwsx0987qa<..>  2010-12-30 13:41:44.673

Czyli nadal jedna strona ?

DBCC IND (5,2139154666,1)WITH TABLERESULTS, NO_INFOMSGS



Już są dwie strony danych, została dodana strona typu LOB, funkcja wskazuje tylko stronę początkową. Co będzie jak dodamy następny rekord?

INSERT test (tekst,dtekst,data)
SELECT tekst,dtekst,data FROM test
go
SELECT sys.fn_PhysLocFormatter(%%physloc%%), * FROM test

--------------

                   id          tekst     dtekst               data
------------------ ----------- ----------------------------------------------------
(1:20636:0)        1           abc       ABCqazwsx0987qa<..>  2010-12-30 13:41:44.673
(1:20636:1)        2           abc       ABCqazwsx0987qa<..>  2010-12-30 13:44:31.423

Wszystko nadal jest na jednej stronie, tak to wygląda ponieważ na pierwszej stronie znajdują się wskaźniki do strolny LOB. Faktycznie dane znajdują się już na trzech stronach