Базы данных Oracle - статьи

         

Столбцы с небольшим количеством значений


Часто утверждается, что "индексы на основе битовых карт подходят для столбцов с небольшим количеством значений". Несколько точнее будет формулировка "с небольшим количеством различных значений". В любом случае, речь идет о столбцах, содержащих сравнительно мало различных значений.

Это утверждение, действительно, достаточно верное, - если его соответствующим образом уточнить и разъяснить. К сожалению, многие, в результате, думают, что индекс на основе битовых карт чудесным образом настолько эффективен, что его можно использовать для доступа к большим частям таблицы способом, не считающимся целесообразным при использовании индекса на основе B*-дерева.

Классическим примером применимости индекса на основе битовых карт является экстремальный случай столбца, представляющего пол. В этом столбце может быть всего два значения (или три, если включить требуемое стандартом ISO значение "n/a" - неизвестен). Мы будем чуть менее экстремальны и рассмотрим пример, основанный на странах, образующих Соединенное Королевство: Англия, Ирландия, Шотландия и Уэльс.

Пусть используются блоки размером 8 Кбайт и строки (весьма типичным) размером 200 байтов, что дает 40 строк в блоке. Вставим в таблицу несколько миллионов строк, обеспечив равномерно случайное распределение по странам. Таким образом, в среднем в каждом блоке будет по 10 строк для каждой страны.

Если использовать индекс на основе битовых карт для доступа ко всем строкам по Англии, придется (10 раз) последовательно прочитать каждый блок таблицы. Вне всякого сомнения, эффективнее будет выполнить полный просмотр таблицы, а не использовать такой индекс.

На самом деле, даже если расширить данные так, чтобы они включали информацию по 40 странам, все равно вполне вероятно получить по одной строке в каждом блоке таблицы. Вероятно, когда данные разрастутся до глобального масштаба (скажем, охватят 640 стран, чтобы строка для данной страны встречалась в среднем лишь в каждом 16-ом блоке), может оказаться дешевле обращаться к ним по индексу на основе битовых карт, а не путем полного просмотра таблицы. Но столбец, имеющий 640 различных значений, вряд ли, на первый взгляд, попадает под определение "с небольшим количеством различных значений".

Конечно, описательные выражения типа "небольшой", "маленький", "близкий к нулю" требуют определенного уточнения. Например, близко ли значение 10000 к нулю? Если сравнивать с десятью миллиардами, то да!

Не используйте неопределенные выражения вроде "небольшое количество". В большинстве случаев, при выборе индексов на основе битовых карт необходимо учитывать только два фактора. Во-первых, количество различных блоков в таблице, в которых может находиться типичное значение индекса - это основной фактор выбора отдельного индекса. Изменение структуры индекса с B*-дерева на набор битовых карт не сделает этот индекс в это отношении лучше чудесным образом. Во-вторых, используемый оптимизатором Oracle механизм комбинирования нескольких битовых индексов делает их действительно полезными.

Рассмотрим следующий пример, основанный на данных по примерно 64-миллионному населению Великобритании.


  • 50 миллионов имеет карие глаза
  • 35 миллионов - женщины
  • 17 миллионов - темноволосые
  • 1,8 миллиона живет в районе Бирмингема
  • 1, 2 миллиона имеет возраст 25 лет
  • 750000 работает в Лондоне


Каждому критерию отдельно соответствует очень много людей, но сколько кареглазых темноволосых женщин в возрасте 25 лет живет в Бирмингеме и работает в Лондоне? Где-то пару десятков.

create table junk as select rownum id from all_objects where rownum <= 8000;

create table t1 nologging pctfree 0 as select /*+ ordered use_nl(v2) */ 'x' facts, mod(rownum,2) sex, mod(rownum,3) eyes, mod(rownum,7) hair, mod(rownum,31) town, mod(rownum,47) age, mod(rownum,79) work, from junk v1, junk v2;

create bitmap index i1 on t1(sex) nologging pctfree 0;

create bitmap index i2 on t1(eyes) nologging pctfree 0;

create bitmap index i3 on t1(hair) nologging pctfree 0;

create bitmap index i4 on t1(town) nologging pctfree 0;

create bitmap index i5 on t1(age) nologging pctfree 0;

create bitmap index i6 on t1(work) nologging pctfree 0;

analyze table t1 estimate statistics;

Рисунок 4. Моделируем население Великобритании.

Отдельный индекс (будь-то на основе B*-дерева или битовых карт) по любому из этих столбцов будет абсолютно бесполезен для выполнения такого запроса к таким данным в СУБД Oracle.

Многостолбцовый индекс на основе B*-дерева по соответствующим шести столбцам может существенно помочь, пока нас не заинтересуют мужчины ростом 180 см. с бородой вместо темноволосых и кареглазых женщин.

Можете поэкспериментировать (см. рис. 4), но понадобиться около 2,0 Гбайт места на диске и пару часов работы процессора с тактовой частотой порядка 500 МГц.

Из-за нехватки места я построил модель поменьше, эмулирующую население порядка 36 миллионов. Время построения и размеры объектов для компьютера с тактовой частотой процессора 600 МГц, ОС Win2000 и сервером Oracle версии 9.2.0.1 представлены в следующей таблице.

Объект Размер (Мбайт) Время построения (мин:сек)
T1 845 16:12
I1 (sex) 11 1:39
I2 (eyes) 16 1:43
I2 (hair) 37 2:17
I4 (town) 40 2:25
I5 (age) 42 2:28
I6 (work) 45 2:42
<

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