четверг, 9 июля 2009 г.

Битовые индексы соединения Oracle DB (bitmap join indexes, BJI)

(http://www.interface.ru/fset.asp?Url=/oracle/or9inewvozmojnosti.htm)
Невозможно оставить без внимания ещё одно оригинальное новшество – битовые индексы соединения (bitmap join indexes, BJI). Это обычные битовые индексы, но построенные по столбцам, которых в индексируемой таблице нет. Например, в таблице продаж (назовем её по традиции Sales) есть код региона продажи, но нет его названия. Название есть в справочнике регионов (Regions). В то же время запрос, выбирающий все продажи по региону с заданным названием, довольно типичен. При его выполнении каждый раз требуется соединение (join) таблиц Sales и Regions. Рассмотрим пример.
Создадим таблицы:
create table Regions
(
region_id number primary key,   -- первичный ключ обязателен для создания BJI
region_name varchar2(200)
);
create table Sales
(
id number primary key,
region_id number,               -- опустим ограничения внешнего ключа
product_id number,
amount number,
sal_date date
);
Выполним запрос:
Select sum(amount)
from sales, regions
where
     regions.region_id = sales.region_id
 and regions.region_name = 'Центр'
Рассмотрим план выполнения этого запроса (это не единственно возможный, но вполне вероятный план). В плане, естественно, присутствует просмотр обеих таблиц и операция их соединения:
SELECT STATEMENT Optimizer=ALL_ROWS
SORT (AGGREGATE)
NESTED LOOPS
  TABLE ACCESS (FULL) OF 'SALES'
  TABLE ACCESS (BY INDEX ROWID) OF 'REGIONS'
    INDEX (UNIQUE SCAN) OF 'REGIONS_PK' (UNIQUE)
Если же это соединение выполнить один раз при построении индекса, и в индексе хранить указатели на строки таблицы Sales вместе с соответствующими названиями регионов из таблицы Regions, то для выполнения вышеописанного запроса таблица Regions вообще не понадобится, и можно избежать очень дорогостоящей операции соединения.
Создадим индекс:
create bitmap index Sales_reg_bji
on Sales(regions.region_name)
from Sales, Regions
where sales.region_id=regions.region_id
Чтобы побудить оптимизатор использовать этот индекс, применим подсказку (hint). В реальности, если таблицы будут достаточно большими, подсказки скорее всего не понадобятся, т.к. стоимость выполнения этого запроса с использованием индекса будет существенно меньше, чем без него:
select /*+ index(sales sales_reg_bji) */
 sum(amount) from sales, regions
 where
       regions.region_id   = sales.region_id
   and regions.region_name = 'Центр'
Рассмотрим план выполнения и убедимся, что просмотр таблицы Regions и операция соединения исчезли:
SELECT STATEMENT Optimizer=ALL_ROWS
SORT (AGGREGATE)
  TABLE ACCESS (BY INDEX ROWID) OF 'SALES'
    BITMAP CONVERSION (TO ROWIDS)
      BITMAP INDEX (SINGLE VALUE) OF 'SALES_REG_BJI'
Средства обеспечения масштабируемости приложений технологию разработки напрямую не затрагивают, но позволяют обойтись без модификации приложения при увеличении объёма данных или количества пользователей.

Ярлыки