Том Кайт о сервере Oracle Database 11g - Кешируйте

ОГЛАВЛЕНИЕ


Кешируйте

Сервер Oracle Database 11g поднимает планку кеширования данных. В прошлом сервер Oracle Database кешировал блоки базы данных. Он мог кешировать эти блоки в различных местах, таких как пул по умолчанию, удерживающий буферный пул или рециклирующий буферный пул. Но он всегда кешировал блоки данных - строительные блоки, используемые для построения результирующих наборов.

Начиная с Oracle Database 11g, сервер может кешировать результирующие наборы! Если у вас есть запрос, который многократно обращается к медленно изменяющимся или никогда не изменяющимся данным, вы обнаружите, что новый серверный кеш результатов выполнения запросов (server results cache) вызовет чрезвычайный интерес. Практически любое приложение может и будет получать выгоду от использования этого кеша.

Если кратко, идея такова: когда вы выполняете запрос, сервер Oracle Database 11g сначала выяснит, а не были ли результаты этого запроса уже вычислены и кешированы другим сеансом или пользователем, если это так, то он извлечет результат из серверного кеша результатов, вместо того, чтобы снова с нуля собирать все нужные блоки базы данных и вычислять результат. Для первого выполнения запроса потребуется столько же времени, сколько и обычно (поскольку вычисляется ответ), а последующие выполнения будут мгновенными, поскольку ответ не вычисляется, а сразу же возвращается.

Я считаю, что это средство аналогично динамическим "материализованным представлениям" (just-in-time materialized view). В сервере Oracle8i Database Release 1 корпорация Oracle ввела понятие материализованных представлений. С помощью такого представления АБД мог создать таблицу итогов, почти так же, как он создавал индексы, и оптимизатор распознавал, что эта таблица итогов существует и, если возможно, использовал ее для ответа на запросы, вместо того, чтобы запрашивать и обрабатывать детальную информацию, которая хранится в базовых таблицах. Этот способ работы хорош, но он скорее статический, очень похожий на схему индексирования. Однако в сервере Oracle Database 11g с помощью серверного кеша результатов материализованные представления создаются и сопровождаются в сущности "на проходе". Этот кеш (динамическое материализованное представление) заполняется при необходимости, без какого-либо вмешательства АБД. В качестве примера я скопирую представление ALL_OBJECTS в таблицу:
SQL> create table t
  2  as
  3  select *
  4    from all_objects;
Table created.
Теперь я создам небольшую функцию, которая формирует отчет - выполняет запрос к этой таблице. Для четкой демонстрации отличий в производительности этого запроса я не буду ничего делать внутри цикла (обычно в нем я печатаю строки и выполняю некоторые вычисления):
SQL> create or replace procedure 
  2  my_function
  3  as
  4  begin
  5    for x in
  6    (select owner,
  7              object_type,
  8              count(*) cnt
  9       from t
 10          group by owner, object_type
 11          order by owner, object_type )
 12    loop
 13          -- do_something
 14          null;
 15    end loop;
 16  end;
 17  /
Procedure created.
Теперь я три раза выполню эту процедуру, засекая время каждого выполнения:

SQL> set timing on

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.54

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.10

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.11

SQL> set timing off
Обратите внимание, для первого выполнения потребовалось существенное время, около 1.5 секунд, из-за физического ввода-вывода, необходимого для чтения данных с диска в обычный буферный кеш. Для второго и третьего выполнения потребовалось намного меньше времени, около 0.1 секунды, поскольку блоки, необходимые для получения ответа запроса, были найдены в кеше, а не на диске. Сравним это с тем, что произойдет, если я к запросу добавлю подсказку "cache the results" (кешировать результаты):
SQL> create or replace procedure 
  2  my_function
  3  as
  4  begin
  5    for x in
  6    (select /*+ result_cache */
  7               owner,
  8               object_type,
  9               count(*) cnt
 10       from t
 11          group by owner, object_type
 12          order by owner, object_type )
 13    loop
 14          -- do_something
 15          null;
 16    end loop;
 17  end;
 18  /
Procedure created.

SQL> set timing on

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.10

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01

SQL> set timing off
Обратите внимание, для первого выполнения потребовалось около 0.1 секунды, поскольку для этого первого выполнения ответ нужно было компоновать, а последующие выполнения были чертовски быстрыми - иногда такими быстрыми, что казались мгновенными.

Еще хорошая вещь об этом - этот кеш автоматически делается недействительным и обновляется сервером базы данных, этот процесс совершенно прозрачен для приложения. Приложение не должно заботиться об устаревших или недействительных результатах. Например, если я обновлю одну строку, изменив, таким образом, результаты:
SQL> update t
  2  set owner = lower(owner)
  3  where rownum = 1;
1 row updated.

SQL> commit;
Commit complete.

- то я вижу следующее:

SQL> set timing on

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.10

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00

SQL> exec my_function
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01

SQL> set timing off
Обратите внимание, что после выполнения оператора UPDATE для первого выполнения запроса снова потребовалось около 0.1 секунды, поскольку нужно было строить новый ответ. От этой работы получают выгоды последующие выполнения, которые кажутся мгновенными.

Я уверен, что, если вы удобно усядетесь и поразмышляете о ваших собственных приложениях, вы сможете найти более одного места, где пригодится серверный кеш результатов. Этот кеш предоставляет собой многие из преимуществ некоторых материализованных представлений, но не требует настройки и административных накладных расходов.