Том Кайт о сервере Oracle Database 11g - Кешируйте
ОГЛАВЛЕНИЕ
Страница 2 из 5
Кешируйте
Сервер 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.
Обратите внимание, для первого выполнения потребовалось существенное время, около 1.5 секунд, из-за физического ввода-вывода, необходимого для чтения данных с диска в обычный буферный кеш. Для второго и третьего выполнения потребовалось намного меньше времени, около 0.1 секунды, поскольку блоки, необходимые для получения ответа запроса, были найдены в кеше, а не на диске. Сравним это с тем, что произойдет, если я к запросу добавлю подсказку "cache the results" (кешировать результаты):
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
SQL> create or replace procedureОбратите внимание, для первого выполнения потребовалось около 0.1 секунды, поскольку для этого первого выполнения ответ нужно было компоновать, а последующие выполнения были чертовски быстрыми - иногда такими быстрыми, что казались мгновенными.
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
Еще хорошая вещь об этом - этот кеш автоматически делается недействительным и обновляется сервером базы данных, этот процесс совершенно прозрачен для приложения. Приложение не должно заботиться об устаревших или недействительных результатах. Например, если я обновлю одну строку, изменив, таким образом, результаты:
SQL> update tОбратите внимание, что после выполнения оператора UPDATE для первого выполнения запроса снова потребовалось около 0.1 секунды, поскольку нужно было строить новый ответ. От этой работы получают выгоды последующие выполнения, которые кажутся мгновенными.
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
Я уверен, что, если вы удобно усядетесь и поразмышляете о ваших собственных приложениях, вы сможете найти более одного места, где пригодится серверный кеш результатов. Этот кеш предоставляет собой многие из преимуществ некоторых материализованных представлений, но не требует настройки и административных накладных расходов.