Buffer cache to specjalny kontener rezydujący wyłącznie w pamięci RAM, który przechowuje odczytane z dysku strony danych. Zawartość bufora jest natomiast odczytywana przez procesor kwerend i przetwarzana zgodnie z logiką zapytania. Odczyt jednej strony danych do bufora to tzw. odczyt fizyczny (
physical read), natomiast odczyt jednej strony danych z bufora do przestrzeni zapytania to tzw. odczyt logiczny (
logical read). Procesor kwerend nigdy bezpośrednio nie sięga do dysku (każda strona danych musi być najpierw odczytana do buffer cache). Po co to wszytko? Przede wszystkim po to, aby minimalizować obciążenie podsystemu IO (czyli dysków), gdyż odczyty logiczne są bardzo szybkie i nieobciążające, czego nie można powiedzieć o odczytach fizycznych. Jeżeli więc jakaś strona danych trafi do bufora, to kolejne zapytania nie będą musiały żądać pobrania tych danych z dysku. Naturalnie nie wszystkie strony danych mogą znaleźć się w buffer cache na dowolnie długi czas, ale przecież nie wszystkie strony są w danym momencie potrzebne. Drugim istotnym powodem istnienia bufora danych są kwestie związane z mechanizmem blokad niskopoziomowych typu
latch i ogólnie mówiąc - z implementacją współbieżności i transakcyjności. W systemie SQL Server mamy jeden buffer cache (zwany także buforem danych lub cachem danych) dla całej instancji, podobnie z resztą jak w przypadku tzw.
procedure cache, który to z kolei przechowuje plany zapytań kwerend ad-hoc i innych obiektów (jak procedury, triggery czy wydoki). Często możemy być zainteresowani uzyskaniem informacji na temat tego, jakie ilości danych przechowywane są w buforze danych w określonym momencie oraz tego, ile MB bufora przypada na strony danych pochodzące z poszczególnych baz. Do takich celów możemy wykorzystać poniższe zapytanie do widoku
sys.dm_os_buffer_descriptors:
SELECT CASE
WHEN (GROUPING(database_id) = 1) THEN '-- TOTAL --'
ELSE DB_NAME(database_id)
END as 'Database name',
CAST(COUNT(page_id)/128.0 as numeric(8,2)) as MB
FROM sys.dm_os_buffer_descriptors
WHERE database_id !=32767
GROUP BY database_id
WITH ROLLUP
ORDER BY COUNT(page_id) DESC;
Trzeba pamiętać, że ilość pamięci RAM jest ograniczona i często procedure cache będzie rywalizował z buffer cache o przestrzeń do zaalokowania. Jeśli więc nagle z procedure cache wypadło nam większość planów zapytań, to warto ustalić przy pomocy powyższego zapytania, co dzieje się w buforze danych. Potencjalnie może się okazać, że tzw.
wild query (np. przypadkowy CROSS JOIN na wielkich zbiorach) spowodowało wrzucenie do buffer cache gigabajtów danych, co w konsekwencji nadmiernie ograniczyło przestrzeń dostępną dla procedure cache.