Кешування і організація пулу, Інші СУБД, Бази даних, статті

Кеш результатів SQL


Доступ до пам’яті набагато швидше, ніж доступ до жорстких дисків, і це, ймовірно, буде мати місце протягом кількох наступних років, до тих пір, поки ми не побачимо деяких значних поліпшень в архітектурі жорстких дисків. Цей факт дає привід для кешування: процесу зберігання даних в пам’яті замість дисків. Кешування – це загальний принцип архітектури бази даних Oracle, в якому користувачі зчитують дані з буфера кешу замість дисків, на яких розташовується база даних.


Переваги кешування особливо помітні у випадку з відносно маленькими таблицями, які мають статичні дані, наприклад, довідковими таблицями, такими як STATES, PRODUCT_CODES і так далі. Розглянемо, проте, випадок великої таблиці CUSTOMERS, яка зберігає відомості про клієнтів компанії. Дані в ній щодо статичні, але не зовсім: таблиця змінюється рідко, коли клієнти додаються або видаляються зі списку. Кешування, ймовірно, мало б тут деякий сенс. Але, якщо таблиця буде якось кешуватися, як можна бути впевненим, що отримаєш вірні дані, коли щось зміниться? У базі даних Oracle 11g є відповідь: використання кеша результатів SQL (SQL Result Cache). Розглянемо наступний запит. Запустимо його, щоб отримати статистику виконання і час відгуку.

SQL> set autot on explain stat
select
state_code,
count(*),
min(times_purchased),
avg(times_purchased)
from customers
group by state_code
/
Ось результати:
ST COUNT(*) MIN(TIMES_PURCHASED) AVG(TIMES_PURCHASED)
— ———- ——————– ——————–
NJ 1 15 15
NY 994898 0 15.0052086
CT 5099 0 14.9466562
MO 1 25 25
FL 1 3 3

5 rows selected.

Elapsed: 00:00:02.57

Execution Plan
———————————————————-
Plan hash value: 1577413243

——————————————————————————–
/ Id / Operation / Name / Rows / Bytes / Cost (%CPU)/ Time /
——————————————————————————–
/ 0 / SELECT STATEMENT / / 5 / 30 / 1846 (25)/ 00:00:23 /
/ 1 / HASH GROUP BY / / 5 / 30 / 1846 (25)/ 00:00:23 /
/ 2 / TABLE ACCESS FULL/ CUSTOMERS / 1000K/ 5859K/ 1495 (7)/ 00:00:18 /
——————————————————————————–

Statistics
———————————————————-
1 recursive calls
0 db block gets
5136 consistent gets
5128 physical reads
0 redo size
760 bytes sent via SQL*Net to client
420 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5 rows processed


Звернемо увагу на наступні моменти:



Оскільки таблиця майже зовсім не змінюється, можна використовувати підказку, яка збереже результати запиту в кеші пам’яті:

select /*+ result_cache */
state_code,
count(*),
min(times_purchased),
avg(times_purchased)
from customers
group by state_code
/

Запит ідентичний першому за винятком підказки. Ось результат (друге виконання цього запиту):

ST   COUNT(*) MIN(TIMES_PURCHASED) AVG(TIMES_PURCHASED)
— ———- ——————– ——————–
NJ 1 15 15
NY 994898 0 15.0052086
CT 5099 0 14.9466562
MO 1 25 25
FL 1 3 3

5 rows selected.

Elapsed: 00:00:00.01

Execution Plan
———————————————————-
Plan hash value: 1577413243

————————————————————————————————–
/ Id / Operation / Name / Rows / Bytes / Cost (%CPU)/ Time /
————————————————————————————————–
/ 0 / SELECT STATEMENT / / 5 / 30 / 1846 (25)/ 00:00:23 /
/ 1 / RESULT CACHE / gk69saf6h3ujx525twvvsnaytd / / / / /
/ 2 / HASH GROUP BY / / 5 / 30 / 1846 (25)/ 00:00:23 /
/ 3 / TABLE ACCESS FULL/ CUSTOMERS / 1000K/ 5859K/ 1495 (7)/ 00:00:18 /
————————————————————————————————–
Result Cache Information (identified by operation id):
——————————————————

1 – column-count=4; dependencies=(ARUP.CUSTOMERS); parameters=(nls); name=”select /*+ result_cache */
state_code,
count(*),
min(times_purchased),
avg(times_purchased)
from customers
group by state_c”

Statistics
———————————————————-
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
760 bytes sent via SQL*Net to client
420 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5 rows processed


Зверніть увагу на деякі відмінності від першого запиту:



Економія часу вражаюча: від 3 секунд до майже нічого! Це завдяки тому, що другий запит, в якому ми використовували кеш, повертає дані безпосередньо з пам’яті бази даних (кеша результатів), а не після виконання запиту.


Кеш результатів SQL – це новий кеш в SGA, подібний буферному кешу або програмної глобальної області. При виконанні запиту з підказкою result_cache, Oracle виконує запит також як будь-який інший запит, але результати зберігаються в кеші результатів SQL. Наступні виклики того ж самого запиту не звертаються до таблиці (або таблиць), а беруть результати з кешу. Розмір кеша визначається кількома параметрами ініціалізації:



















Параметр  Опис 
result_cache_max_size Максимальний розмір кеша (наприклад, 5M для 5 MB). Якщо встановити в 0, кеш результатів буде повністю виключений.
result_cache_max_result пределяет відсоток від максимального розміру кешу (result_cache_max_size), який може використовуватися одним запитом.
result_cache_mode Якщо задано значення FORCE, то всі запити кешуються, якщо вони вміщаються в кеш. Значення за замовчуванням MANUAL означає, що кешуються тільки запити з підказкою.
result_cache_remote_expiration Визначає кількість хвилин, що результат в кеші, який звертався до віддаленого об’єкту, залишається дійсним. За замовчуванням 0.


Тепер логічне запитання: що відбувається, коли змінюються рядки таблиці? Чи отримає запит нове значення або старе? Дійсно, давайте подивимося, що відбувається. З іншого сесії SQL * Plus змінимо рядок таблиці:

SQL> update customers set times_purchased = 4
2 where state_code = “FL”;

1 row updated.


але не будемо виконувати commit. З першого вікна, в якому ми запускали запит в перший раз, запустимо його знову. Використовується ще кешированний результат, оскільки зміни ще не зафіксовано. Сесія, яка виконує запит, бачить все ще актуальну версію даних, і кеш все ще дійсний.


Тепер у сесії, в якій виконувалося оновлення, виконаємо commit і запустимо запит.

ST   COUNT(*) MIN(TIMES_PURCHASED) AVG(TIMES_PURCHASED)
— ———- ——————– ——————–
NJ 1 15 15
NY 994898 0 15.0052086
CT 5099 0 14.9466562
MO 1 25 25
FL 1 4 4

Зверніть увагу, що дані для FL змінили значення на 4 автоматично. Зміни в основній таблиці просто зробили кеш недійсним, що призвело до його динамічному оновленню при наступному запиті. Ви гарантовано отримаєте правильні результати незалежно від того, чи використовується кеш результатів SQL чи ні.


Відмінності від матеріалізованих представлень


Ті, хто знайомий з матеріалізованими уявленнями (MVs – МП) можуть здивуватися, чому ця функціональність (кеш результатів SQL) відрізняється від тієї (матеріалізованих представлень). Відповідь: багатьом. Зовні вони здаються схожими – обидва якимось чином зберігають результати і видають відповіді з цього збереженого множини, але на цьому схожість закінчується. Матеріалізовані уявлення зберігають дані в пам’яті бази даних, а кеші результатів SQL – в оперативній пам’яті, вони не використовують додатковий дисковий простір і зникають, коли екземпляр бази даних зупиняється або вичерпується простір в кеші результатів.


Крім того, МП статичні; коли дані в основних таблицях змінюються, матеріалізовані уявлення не знають про це. До тих пір поки матеріалізовані уявлення не буде поновлено, користувачі можуть або отримувати застарілі дані, якщо параметр query_rewrite_integrity встановлений в значення stale_tolerated, або перенаправити базовий запит до основних таблиць, що займе набагато більше часу. При використанні ж кеша результатів SQL немає необхідності явно оновлювати кеш, він автоматично оновиться при наступному виконанні запиту.


МП застосовують набагато складніший му алгоритм переписування. Кешированний результат повторно використовується тільки тоді, якщо той же самий запит (або його фрагмент) виконується знову, після того як він був в перший раз поміщений в кеш (і витягнуті дані не змінювалися). Переадресовані до МП запити отримують додатковий виграш від того, що в них можна згортати дані з МП, виконувати з’єднання з таблицями або іншими матеріалізованими уявленнями, а також застосовувати додаткові предикати, що прагну в середовищі сховищ даних.


Отже, МП і кеші результатів SQL не обов’язково порівняти або взаємозамінні, кожен підхід має свої власні переваги.


Підзапити


Кеш результату SQL можна використовувати в підзапит. Розглянемо наступний запит:

select prod_subcategory, revenue
from (
select /*+ result_cache */ p.prod_category,
p.prod_subcategory,
sum(s.amount_sold) revenue
from products p, sales s
where s.prod_id = p.prod_id
and s.time_id between to_date(“01-jan-1990″,”dd-mon-yyyy”)
and to_date(“31-dec-2007″,”dd-mon-yyyy”)
group by rollup(p.prod_category, p.prod_subcategory)
)
where prod_category = “software/other”
/

У цьому запиті кешування виконується в підзапит у вбудованому поданні. Таким чином, у той час як внутрішній запит залишається таким же, зовнішній запит може змінюватися, все ще використовуючи кеш.


Щоб перевірити, скільки пам’яті використовується для кеша результатів SQL в базі даних, можна використовувати стандартний пакет dbms_result_cache, як показано нижче:

SQL> set serveroutput on size 999999
SQL> execute dbms_result_cache.memory_report
R e s u l t C a c h e M e m o r y R e p o r t
[Parameters]
Block Size = 1K bytes
Maximum Cache Size = 2560K bytes (2560 blocks)
Maximum Result Size = 128K bytes (128 blocks)
[Memory]
Total Memory = 126736 bytes [0.041% of the Shared Pool]
… Fixed Memory = 5132 bytes [0.002% of the Shared Pool]
… Dynamic Memory = 121604 bytes [0.040% of the Shared Pool]
……. Overhead = 88836 bytes
……. Cache Memory = 32K bytes (32 blocks)
……….. Unused Memory = 21 blocks
……….. Used Memory = 11 blocks
…………… Dependencies = 4 blocks (4 count)
…………… Results = 7 blocks
………………. SQL = 5 blocks (4 count)
………………. Invalid = 2 blocks (2 count)

PL/SQL procedure successfully completed.


Якщо необхідно з якоїсь причини скинути вміст кеша (і кеш результатів, і кеш функцій, описаний нижче) можна використовувати:

begin
dbms_result_cache.flush;
end;

Після виконання вищенаведеного оператора при запуску вихідного запиту до таблиці CUSTOMERS з підказкою result_cache, ви побачите, що запит знову виконується 3 секунди.


Звичайно, після першого виконання запиту результати знову будуть кешованими і при наступних виконаннях значення будуть знову вибиратися з кеша результатів і, отже, запит буде виконуватися набагато швидше. Якщо необхідно зробити недійсним кеш тільки для однієї таблиці, а не весь кеш повністю, можна використовувати наступний оператор:

begin
dbms_result_cache.invalidate(“ARUP”,”CUSTOMERS”);
end;

Існує кілька подань словника даних, які показують статистику кеша результатів SQL:



















Параметр  Опис 
V$RESULT_CACHE_STATISTICS Показує різні настройки, особливо використання пам’яті
V$RESULT_CACHE_MEMORY Показує різні ділянки пам’яті, які становлять кеш результатів SQL
V$RESULT_CACHE_OBJECTS Показує об’єкти, які становлять кеш результатів SQL
V$RESULT_CACHE_DEPENDENCY Показує залежності між різними об’єктами, складовими кеш результатів SQL


Кеш результатів SQL дозволяє кешувати результати запитів, які звертаються до великої кількості даних. Коли основна таблиця змінюється, кеш автоматично стає недійсним, без вашого втручання або створення будь-якого додаткового коду.


Кеш результатів PL / SQL функцій


Припустимо, що замість SQL-запиту існує PL / SQL-функція, яка повертає значення. Це звичайної прийом: використовувати функцію для повернення значення, щоб зробити код більш модульним. Розглянемо випадок двох таблиць: CUSTOMERS, яка зберігає інформацію про всіх клієнтів разом з state_code. Інша таблиця TAX_RATE зберігає податкову ставку кожного штату. Для отримання податкової ставки для клієнта необхідно в запиті з’єднати таблиці. Тому, щоб спростити завдання, можна написати функцію, показану нижче, яка приймає ID клієнта як параметр і повертає податкову ставку в залежності від state_code:

create or replace function get_tax_rate
(
p_cust_id customers.cust_id%type
)
return sales_tax_rate.tax_rate%type
is
l_ret sales_tax_rate.tax_rate%type;
begin
select tax_rate
into l_ret
from sales_tax_rate t, customers c
where c.cust_id = p_cust_id
and t.state_code = c.state_code;
— simulate some time consuming
— processing by sleeping for 1 sec
dbms_lock.sleep (1);
return l_ret;
exception
when NO_DATA_FOUND then
return NULL;
when others then
raise;
end;
/

Виконаємо функцію кілька разів, як показано нижче. Не забудьте встановити параметр timing в значення on, щоб записати час виконання в кожному випадку.

SQL> select get_tax_rate(1) from dual;

GET_TAX_RATE(1)
—————
6

1 row selected.

Elapsed: 00:00:01.23
SQL> select get_tax_rate(1) from dual;

GET_TAX_RATE(1)
—————
6

1 row selected.

Elapsed: 00:00:01.17


Послідовно видається приблизно однаковий час для кожного виконання. (Я свідомо додав оператор sleep, щоб збільшити час виконання функції; інакше значення б поверталося занадто швидко.) Якщо розглянути код, можна помітити, що функція, ймовірно, буде повертати одне і те ж значення при кожному виклику. Клієнт не часто змінює штат, і податкова ставка для штату змінюється рідко, тому дуже ймовірно, що для даного клієнта податкова ставка буде однаковою при всіх виконаннях функції. Ставка зміниться тільки, якщо зміниться податкова ставка штату, або клієнт переїде в інший штат. Отже, як щодо кешування результатів цієї функції?


База даних Oracle 11g дозволяє зробити саме це. Дозволити кешування результатів функції можна, просто додавши пропозицію result_cache. Але як щодо випадку, коли в штаті змінюється податкова ставка або коли клієнт переїжджає в інший штат? Є можливість визначити залежність від базових таблиць, так що будь-які дані, що змінюються в цих таблицях, викликатимуть недійсність і подальше перестроювання кеша результатів функції. Ось та ж функція з доданим пропозицією result cache (виділено жирним шрифтом):

create or replace function get_tax_rate
(
p_cust_id customers.cust_id%type
)
return sales_tax_rate.tax_rate%type
result_cache
relies_on (sales_tax_rate, customers)

is
l_ret sales_tax_rate.tax_rate%type;
begin
select tax_rate
into l_ret
from sales_tax_rate t, customers c
where c.cust_id = p_cust_id
and t.state_code = c.state_code;
— simulate some time consuming
— processing by sleeping for 1 sec
dbms_lock.sleep (1);
return l_ret;
exception
when NO_DATA_FOUND then
return NULL;
when others then
raise;
end;
/

Після цього зміни створіть і виконайте функцію наступним чином:

SQL> select get_tax_rate(1) from dual;

GET_TAX_RATE(1)
—————
6

1 row selected.

Elapsed: 00:00:01.21


Час виконання – 1.21 секунди, як і раніше, але давайте подивимося на наступне виконання:

SQL> select get_tax_rate(1) from dual;

GET_TAX_RATE(1)
—————
6

1 row selected.

Elapsed: 00:00:00.01


Час виконання – всього лише 0.01 секунди! Що сталося? Функція в перший раз нормально виконалася за 1.21 секунду. Але важлива відмінність цього разу полягає в тому, що при її виконанні результат кешуватися. При наступних викликах функція не виконується, результат просто береться з кешу. Тому немає очікування в 1 секунду, як це було в коді функції.


Кешування виконувалося тільки для клієнта з ідентифікатором (customer_id) рівним 1. Що якщо спробувати виконати функцію для іншого клієнта?

SQL> select get_tax_rate(&n) from dual;
Enter value for n: 5
old 1: select get_tax_rate(&n) from dual
new 1: select get_tax_rate(5) from dual

GET_TAX_RATE(5)
—————
6

1 row selected.

Elapsed: 00:00:01.18
SQL> /
Enter value for n: 5
old 1: select get_tax_rate(&n) from dual
new 1: select get_tax_rate(5) from dual

GET_TAX_RATE(5)
—————
6

1 row selected.

Elapsed: 00:00:00.00
SQL> /
Enter value for n: 6
old 1: select get_tax_rate(&n) from dual
new 1: select get_tax_rate(6) from dual

GET_TAX_RATE(6)
—————
6

1 row selected.

Elapsed: 00:00:01.17


Як можна бачити, при першому виконанні з кожним значенням параметра результат кешується. Наступні виклики вибирають значення з кешу. Коли ви продовжуєте виконувати функцію для кожного клієнта, кеш збільшується.


Зверніть увагу на пропозицію “relies on” в коді функції. Воно говорить функції, що кеш залежить від двох таблиць: customers і tax_rate. Якщо дані в цих таблицях зміняться, кеш повинен бути оновлений. Оновлення відбувається автоматично без вашого втручання. Якщо дані не змінювалися, кеш продовжує надавати кешовані значення настільки швидко, наскільки це можливо.


Якщо з якихось причин необхідно обійти кеш, можна викликати процедуру поставляється пакета DBMS_RESULT_CACHE:

SQL> exec dbms_result_cache.bypass(true);

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
SQL> select get_tax_rate(&n) from dual;
Enter value for n: 6
old 1: select get_tax_rate(&n) from dual
new 1: select get_tax_rate(6) from dual

GET_TAX_RATE(6)
—————
6

1 row selected.

Elapsed: 00:00:01.18


Як видно з часу виконання, кеш не використовувався.


Порівняння кешування та пакетних змінних


Виконувати кешування значень в пам’яті можна також, використовуючи пакетні змінні: або скалярний тип даних, або PL / SQL колекцію – для кеша результатів SQL, також як і для кеша PL / SQL-функції. Додаток може звертатися до змінної швидше, ніж до рядку таблиці або функції. Змінні, що зберігаються в пам’яті, діють в деякому сенсі подібно кешу, так яке ж перевагу має кеш результатів SQL?


Відмінностей багато. Після виконання функції для клієнта з cust_id = 5, з іншої сесії виконайте функцію для цього ж клієнта:

SQL> select get_tax_rate(&n) from dual
2 /
Enter value for n: 5
old 1: select get_tax_rate(&n) from dual
new 1: select get_tax_rate(5) from dual

GET_TAX_RATE(5)
—————
6

1 row selected.

Elapsed: 00:00:00.00


Зверніть увагу на час виконання; воно означає, що результати приходять з кеша, а не від виконання функції. Отже, хоча навіть ця функція і не кешувати в цій сесії, вона все одно використовувалася з кеша другого сесії, що викликала її.


Кеш існує для примірника база даних, не для сесії. Ця можливість зробити кешування в одній сесії доступним всім іншим дуже відрізняється від використання пакетних змінних, що зберігають в пам’яті значення, видиме тільки в цій сесії.


До того ж пакетні змінні нічого не знають про зміни базових таблиць. Їх необхідно оновлювати вручну, коли дані змінюються; інакше програми отримають застарілі дані. Кеш результатів SQL, як і кеш PL / SQL функцій, автоматично оновлюється, коли змінюються дані базових таблиць; користувацького втручання не потрібно.


Клієнтський кеш результатів запиту


Розглянемо ситуацію, коли клієнт повинен викликати одні й ті ж дані через повільне з’єднання з мережею. Хоча база даних може відправити результати клієнту з кешу майже негайно, результат повинен ще добратися по проводах до клієнта, що збільшує загальний час виконання. Існують спеціалізовані проміжні оболонки, такі як Oracle Coherence для кешування даних в Java, PHP і Ruby, але що якби існував загальний спосіб кешування даних на клієнтському рівні?


База даних Oracle 11g надає для цих цілей клієнтський кеш результатів запиту (Client Query Result Cache). Всі клієнтські стеки бази даних, які використовують драйвери OCI8 (C, C + +, JDBC-OCI і так далі), можуть використовувати цю нову можливість, яка дозволяє клієнтам кешувати результати SQL-запитів локально, а не на сервері. У результаті клієнтський кеш результатів запиту надає наступні переваги:



Все, що потрібно зробити, щоб використати цю можливість – це встановити параметр ініціалізації:

CLIENT_RESULT_CACHE_SIZE = 1G

Цей параметр визначає клієнтський кеш розміром в 1 Гб, який є сумою кешів на всіх клієнтах. (Це статичний параметр, тому необхідно зупинити базу даних, щоб його встановити.) Можна налаштувати кеші на кожному клієнті, визначивши інші параметри у файлі SQLNET.ORA на стороні клієнта:
















Параметр  Опис 
OCI_RESULT_CACHE_MAX_SIZE Визначає розмір кеша для цього конкретного клієнта
OCI_RESULT_CACHE_MAX_RSET_SIZE Визначає максимальний розмір наборів результатів
OCI_RESULT_CACHE_MAX_RSET_ROWS Схожий на попередній, але визначає кількість рядків в наборах результатів


Давайте подивимося це в дії. Ось простий Java код, який приєднується до бази даних, використовуючи драйвер OCI8, і виконує SQL оператор:

select /*+ result_cache */ * from customers. 

Підказка вказує оператору, що необхідно кешувати результат (інші параметри вже налаштовані).

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class CacheTest {
private String jdbcURL = “jdbc:oracle:oci8:@PRONE3”;
private Connection conn = null;
public CacheTest( ) throws ClassNotFoundException {
Class.forName(“oracle.jdbc.driver.OracleDriver”);
}
public static void main(String[] args) throws ClassNotFoundException, SQLException {
CacheTest check = new CacheTest();
check.dbconnect();
check.doSomething();
}
public void dbconnect() throws SQLException {
System.out.println(“Connecting with URL=”+jdbcURL+” as arup/arup”);
try {
conn = DriverManager.getConnection( jdbcURL, “arup” , “arup”);
System.out.println(“Connected to Database”);
} catch (SQLException sqlEx) {
System.out.println(” Error connecting to database : ” + sqlEx.toString());
}
}
public void doSomething() throws SQLException {
Statement stmt = null;
ResultSet rset = null;
try {
stmt = conn.createStatement();
System.out.println(“Created Statement object”);
rset = stmt.executeQuery(“select /*+ result_cache */ * from customers”);
System.out.println(“Retrieved ResultSet object”);
if(rset.next())
System.out.println(“Result:”+rset.getString(1));
} catch (SQLException sqlEx) {
} finally {
try {
System.out.println(“Closing Statment & ResultSet Objects”);
if (rset != null) rset.close();
if (stmt != null) stmt.close();
if (conn != null) {
System.out.println(“Disconnecting…”);
conn.close();
System.out.println(“Disconnected from Database”);
}
} catch (Exception e) { }
}
}
}

Збережіть файл як CacheTest.java і потім відкомпілюйте код:

$ORACLE_HOME/jdk/bin/javac CacheTest.java

Тепер виконайте відкомпільований клас:

$ORACLE_HOME/jdk/bin/java -classpath .:$ORACLE_HOME/jdbc/lib/ojdbc5.jar CacheTest
Connecting with URL=jdbc:oracle:oci8:@PRONE3 as arup/arup
Connected to Database
Created Statement object
Retrieved ResultSet object
Result :M
Closing Statment & ResultSet Objects
Disconnecting…
Disconnected from Database

Виконайте це кілька разів. Після декількох виконань можна бачити, що клієнт кешувати значення за допомогою динамічних уявлень, показаних нижче:

select * from client_result_cache_stats$
/
select * from v$client_result_cache_stats
/

Клієнтський кеш результатів запиту дуже підходить для довідкових таблиць, які зазвичай не змінюються. (А якщо вони зміняться, кеш оновиться.) Він відрізняється від кеша результатів SQL, який розташовується на сервері. Оскільки клієнт кешує результати, у клієнта немає необхідності звертатися до сервера, щоб отримати дані, що не тільки зберігає пропускну здатність, але й цикли ЦПУ на сервері. Більш детальну інформацію можна знайти в Oracle Call Interface Programmers Guide.


Організація пулу постійних з’єднань бази даних


У традиційній архітектурі клієнт / сервер існує відповідність один до одного між користувальницької сесією і з’єднанням бази даних. Однак у системі, заснованої на Web, це може бути не так.


Засновані на Web системи є “безстатуснимі” по своїй природі: при зверненні до сторінки встановлюється з’єднання з базою даних, а коли завантаження сторінки завершена, з’єднання з базою даних розривається. Пізніше, коли користувач знову звернеться до цієї сторінки, буде встановлено нове з’єднання, яке буде розірвано після досягнення бажаного результату. Цей процес позбавляє від необхідності керувати великою кількістю одночасних з’єднань.


Встановлення з’єднання досить дорого за своїми накладних витрат, тому кешування з’єднань є важливою вимогою в таких програмах. У цій моделі, коли сторінці необхідно з’єднання з базою даних, з пулу виштовхується одне з уже встановлених з’єднань. Після того як робота зроблена, Web сесія повертає з’єднання назад в пул.


Однак існують проблеми з традиційною клієнт / серверної організацією або організацією пулу на середньому рівні:



Щоб уникнути цієї проблеми база даних Oracle 11g надає пул, розташований на сервері, який називається пул постійних з’єднань бази даних (Database Resident Connection Pool – DRCP). Цей пул доступний всім клієнтам, які використовують OCI драйвера, включаючи C, C + +, і PHP.


За замовчуванням база даних Oracle 11g поставляється з вже встановленим пулом з’єднань, але він відключений. Щоб запустити його, треба виконати:

execute dbms_connection_pool.start_pool;

Тепер, щоб замість звичайної сесії використовувати з’єднання, що зберігаються в пулі, все, що необхідно зробити, це додати рядок (SERVER = POOLED) у вміст TNS, як показано нижче:

PRONE3_POOL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = prolin3.proligence.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = POOLED)
(SID = PRONE3)
)
)

Тепер клієнти можуть підключатися до пулу з’єднань (connection pool), використовуючи рядок з’єднання PRONE3_POOL. Програми будуть взімодействовать з пулом, а не з сервером. Якщо використовується стандартна рядок з’єднання з файлу TNSNAMES.ORA, слід застосувати фразу POOLED. Наприклад в PHP, це виглядає так:

$c = oci_pconnect(“myuser”,”mypassword”,”prolin3.proligence.com/PRONE3:POOLED”);
або
$c = oci_pconnect(“myuser”, “mypassword”,”PRONE3_POOLED”);

У вищенаведеному описі ми запускали пул за замовчуванням, який поставляється з Oracle з опцією за замовчуванням. Можна використовувати процедуру CONFIGURE_POOL в стандартному пакеті DBMS_CONNECTION_POOL:


































Параметр  Опис 
POOL_NAME Ім’я пулу. Використовуйте “” (дві одинарних лапки для пулу за замовчуванням)
MINSIZE Мінімальна кількість сесій, що зберігаються в пулі
MAXSIZE Максимальна кількість сесій, що зберігаються в пулі
INCRSIZE Коли опитуваний сервер недоступний, пул створює задану кількість нових з’єднань
SESSION_CACHED_CURSORS Включає кешування курсорів сесії
INACTIVITY_TIMEOUT Якщо сесія не використовується протягом цього часу, то вона від’єднується
MAX_THINK_TIME Після того як клієнт отримав з’єднання з пулу, він повинен виконати SQL оператор протягом цього часу, інакше клієнт втратить з’єднання
MAX_USE_SESSION Максимальна кількість разів, що з’єднання може бути взято і поміщено назад в пул
MAX_LIFETIME_SESSIONE Як довго сесія повинна існувати


Функціональність DRCP дуже важлива, оскільки один пул може підтримувати десятки тисяч одночасно працюючих користувачів на вигідній основі. Більш того, один пул може розділятися між багатьма клієнтами або вузлами середнього рівня, і в конфігурації RAC і Data Guard комбінація DRCP і подій FAN надають можливість швидкого подолання відмови сполук.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*