Oracle для профессионалов

         

Буферный кеш


До сих пор мы рассматривали небольшие компоненты области SGA. Теперь переходим к составляющей, которая достигает огромных размеров. В буферном кеше сервер Oracle хранит блоки базы данных перед их записью на диск, а также после считывания с диска. Это принципиально важный компонент SGA. Если сделать его слишком маленьким, запросы будут выполняться годами. Если же он будет чрезмерно большим, пострадают другие процессы (например, выделенному серверу не хватит пространства для создания области PGA, и он просто не запустится).

Блоки в буферном кеше контролируются двумя списками. Это список "грязных" блоков, которые должны быть записаны процессом записи блоков базы данных (это DBWn; его мы рассмотрим несколько позже). Есть еще список "чистых" блоков, организованный в Oracle 8.0 и предыдущих версиях в виде очереди (LRU — Least Recently Used). Блоки упорядочивались по времени последнего использования. Этот алгоритм был немного изменен в Oracle 8i и последующих версиях. Вместо физического упорядочения списка блоков, сервер Oracle с помощью счетчика, связанного с блоком, подсчитывает количество обращений ("touch count") при каждом обращении (hit) к этому блоку в буферном кеше. Это можно увидеть в одной из действительно "магических" таблиц X$. Эти таблицы не описаны в документации Oracle, но информация о них периодически просачивается.

Таблица X$BH содержит информацию о блоках в буферном кеше. В ней можно увидеть, как "счетчик обращений" увеличивается при каждом обращении к блоку. Сначала необходимо найти блок. Мы используем блок таблицы DUAL — специальной таблицы, состоящей из одной строки и одного столбца, которая есть во всех базах данных Oracle. Необходимо найти соответствующий номер файла и номер блока в файле:

tkyte@TKYTE816> select file_id, block_id 2 from dba_extents 3 where segment_name = 'DUAL' and owner = 'SYS';

FILE_ID BLOCK_ID ---------- ---------- 1 465

Теперь можно использовать эту информацию для получения "счетчика обращений" для этого блока:


sys@TKYTE816> select tch from x$bh where file# = 1 and dbablk = 465;

TCH ---------- 10

sys@TKYTE816> select * from dual;

D - X

sys@TKYTE816> select tch from x$bh where file# = 1 and dbablk = 465;

TCH ---------- 11

sys@TKYTE816> select * from dual;

D - X

sys@TKYTE816> select tch from x$bh where file# = 1 and dbablk = 465;

TCH ---------- 12

При каждом обращении к блоку увеличивается значение счетчика. Использованный буфер больше не переносится в начало списка. Он остается на месте, а его "счетчик обращений" увеличивается. Блоки со временем перемещаются по списку естественным путем, поскольку измененные блоки переносятся в список "грязных" (для записи на диск процессом DBWn). Кроме того, если несмотря на повторное использование блоков буферный кеш заполнился, и блок с небольшим значением "счетчика обращений" удаляется из списка, он возвращается с новыми данными примерно в середину списка. Полный алгоритм управления списком довольно сложный и меняется с каждой новой версией Oracle. Подробности его работы несущественны для разработчиков, достаточно помнить, что интенсивно используемые блоки кешируются надолго, а редко используемые — долго в кеше не задерживаются.

Буферный кеш в версиях до Oracle 8.0 представлял собой один большой кеш. Все блоки кешировались одинаково, никаких средств деления пространства буферного кеша на части не существовало. В Oracle 8.0 добавлена возможность создания буферных пулов. С ее помощью можно зарезервировать в буферном кеше место для сегментов (как вы помните, сегменты соответствуют таблицам, индексам и т.д.). Появилась возможность выделить место (буферный пул) достаточного размера для размещения целиком в памяти, например, таблиц-"справочников". При чтении сервером Oracle блоков из этих таблиц они кешируются в этом специальном пуле. Они будут конфликтовать за место в пуле только с другими помещаемыми в него сегментами. Остальные сегменты в системе будут "сражаться" за место в стандартном буферном пуле. При этом повышается вероятность их кеширования: они не выбрасываются из кеша как устаревшие при считывании других, не связанных с ними блоков. Буферный пул, обеспечивающий подобное кеширование, называется пулом KEEP. Блоками в пуле KEEP сервер управляет так же, как в обычном буферном кеше. Если блок используется часто, он остается в кеше; если к блоку некоторое время не обращались и в буферном пуле не осталось места, этот блок выбрасывается из пула как устаревший.

Можно выделить еще один буферный пул. Он называется пулом RECYCLE. В нем блоки выбрасываются иначе, чем в пуле KEEP. Пул KEEP

предназначен для продолжительного кеширования "горячих" блоков. Из пула RECYCLE блок выбрасывается сразу после использования. Это эффективно в случае "больших" таблиц, которые читаются случайным образом. (Понятие "большая таблица" очень относительно; нет эталона для определения того, что считать "большим".) Если в течение разумного времени вероятность повторного считывания блока мала, нет смысла долго держать такой блок в кеше. Поэтому в пуле RECYCLE блоки регулярно перечитываются.

...


Содержание раздела