Объекты пользователдьской схемы БД(таблицы, индексы, кластеры)
Таблицы
Прежде чем перейти к деталям, определим каждый тип таблиц. В Oracle 8i - семь
основных типов таблиц.
• Таблицы, организованные в виде кучи. Это "обычные", стандартные таблицы базы
данных. Данные управляются по принципу "кучи". При добавлении данных ис-
пользуется первое же свободное место в сегменте, достаточное для их размеще-
ния. При удалении данных из таблицы освободившееся место может повторно ис-
пользоваться следующими операторами INSERT и UPDATE. Вот откуда название
"организованные в виде кучи" для таких таблиц. "Куча" - это пространство па-
мяти, используемое достаточно случайным образом.
• Таблицы, организованные по индексу. Такая таблица хранится в структуре индекса.
Это предполагает физическое упорядочение ее строк. Если в обычной таблице дан-
ные вставляются в любое свободное место, в таблице, организованной по индек-
су, хранимые данные отсортированы по первичному ключу.
• Таблицы в кластере. Хранение таблицы в кластере дает два преимущества. Во-
первых, несколько таблиц можно хранить вместе. Обычно в блоке хранятся дан-
ные только одной таблицы. В кластере же в одном блоке могут храниться данные
нескольких таблиц. Во-вторых, все данные, содержащие одно и то же значение
ключа кластера, также хранятся вместе. Данные "кластеризованы" вокруг значе-
ния ключа кластера. Ключ кластера строится с помощью индекса на основе В*-
дерева.
• Таблицы в хеш-кластере. Аналогичны представленным ранее таблицам в класте-
ре, но, вместо индекса на основе В*-дерева, для поиска блока данных по ключу
кластера используется хеширование ключа. В хеш-кластере сами данные (образ-
но говоря) и есть индекс. Это хорошо подходит для чтения данных, соответству-
ющих определенному значению ключа.
• Вложенные таблицы. Часть объектно-реляционных расширений сервера Oracle.
Это просто генерируемые и поддерживаемые системой дочерние таблицы связан-
ные как предок-потомок. Они устроены аналогично таблицам ЕМР и DEPT в
схеме SCOTT. Таблицу ЕМР можно считать дочерней по отношению к таблице
DEPT, поскольку в таблице ЕМР есть внешний ключ, DEPTNO, ссылающийся
на таблицу DEPT. Главное различие в том, что это - не "отдельные" таблицы,
как ЕМР.
• Временные таблицы. В этих таблицах сохраняются черновые данные на время
транзакции или сеанса. При необходимости для этих таблиц выделяются времен-
ные экстенты из временного табличного пространства пользователя. Каждый се-
анс будет "видеть" только выделенные им самим экстенты и никогда не "увидит"
данные, созданные в других сеансах.
• Объектные таблицы. Это таблицы, создаваемые на основе объектного типа. Они
имеют специальные атрибуты, отсутствующие у необъектных таблиц, например
генерируемый системой псевдостолбец REF (идентификатор объекта) для каждой
строки. Объектные таблицы фактически являются отдельным случаем обычных,
организованных по индексу и временных таблиц, и могут включать вложенные
таблицы.
Имеется несколько общих свойств таблиц, не зависящих от их типа.
• Таблица может иметь до 1000 столбцов, хотя я не рекомендовал бы использовать
такие таблицы без крайней необходимости. Таблицы наиболее эффективно рабо-
тают при количестве столбцов, намного меньшем, чем 1000.
• Таблица может иметь практически неограниченное количество строк. Хотя при
этом придется столкнуться с другими ограничениями. Например, табличное про-
странство может обычно состоять не более чем из 1022 файлов. Пусть использу-
ются файлы размером 32 Гбайт, тогда получаем 32704 Гбайт в каждом табличном
пространстве. Это означает - 2143289344 блока по 16 Кбайт каждый. В один та-
кой блок можно вместить 160 строк размером от 80 до 100 байт. Это дает в итоге
342926295040 строк. Однако если фрагментировать таблицу, это количество мож-
но увеличить в десять раз. Теоретически ограничения, конечно, есть, но прежде
чем они будут достигнуты, придется столкнуться с другими, практическими ог-
раничениями.
• Таблица может иметь столько индексов, сколько имеется перестановок столбцов
(и перестановок функций от этих столбцов), но не более 32 столбцов, хотя и в
этом случае будут практические ограничения на количество реально создаваемых
и сопровождаемых индексов.
• Нет ограничения на количество таблиц. И в этом случае практические ограниче-
ния будут держать количество таблиц в разумных границах. Миллионов таблиц у
вас не будет (такое количество сложно создать и поддерживать), но тысячи таб-
лиц поддерживаются элементарно.
Индексы
Индексирование - очень важный аспект проектирования и разработки приложения.
Если индексов слишком много, снизится производительность операторов ЯМД. Если ин-
дексов не хватает, снизится производительность запросов (а следовательно, вставок, из-
менений и удалений). Правильное решение этой проблемы позволит обеспечить высо-
кую производительность приложений.
СУБД Oracle предлагает много различных типов индексов.
• Индексы на основе В*-дерева. Эти индексы называют "обычными". Они, несом-
ненно, чаще всего используются в СУБД Oracle, да и в других СУБД. Аналогич-
ные по конструкции двоичному дереву, они обеспечивают быстрый доступ по клю-
чу к отдельной строке или диапазону строк, требуя обычно очень немного чтений
для поиска соответствующей строки. Индекс на основе В*-дерева имеет несколь-
ко подтипов:
Таблицы, организованные по индексу. Это таблицы, хранящиеся в структуре
В*-дерева. Они достаточно подробно описывались в главе 6, посвященной таб-
лицам. В соответствующем разделе главы 6 рассматривались физические струк-
туры, в которых хранятся В*-деревья, так что к этой теме мы возвращаться не
будем.
Индексы кластера на основе В*-дерева. Они немного отличаются от обычных, ис-
пользуются для индексации ключей кластера (см. соответствующий раздел в гла-
ве 6) и отдельно в этой главе рассматриваться не будут. Они используются не для
перехода от ключа к строке, а для перехода от ключа кластера к блоку, содержа-
щему строки, связанные с этим ключом.
Индексы с обращенным ключом. Это индексы на основе В*-дерева, байты ключа
в которых инвертированы. Это используется для более равномерного распреде-
ления записей по индексу при вводе возрастающих значений ключей. Предполо-
жим, при использовании последовательности для генерации первичного ключа
генерируются значения 987500, 987501, 987502 и т.д. Поскольку это последователь-
ные значения, они будут попадать в один и тот же блок индекса, конкурируя за
него. В индексе с обращенным ключом сервер Oracle будет индексировать значе-
ния 205789, 105789, 005789. Эти значения обычно будут далеко отстоять друг от
друга в индексе, и вставки в индекс будут распределены по нескольким блокам.
342 Глава 7
Индексы по убыванию. Далее индексы по убыванию не будут выделяться как от-
дельный тип. Однако поскольку они только появились в Oracle 8i, то заслужива-
ют отдельного рассмотрения. Индексы по убыванию позволяют отсортировать
данные в структуре индекса от "больших" к "меньшим" (по убыванию), а не от
меньших к большим (по возрастанию). Мы разберемся, почему это важно и как
такие индексы работают.
• Индексы на основе битовых карт. Обычно в В*-дереве имеется однозначное со-
ответствие между записью индекса и строкой - запись индекса указывает на стро-
ку. В индексе на основе битовых карт запись использует битовую карту для ссылки
на большое количество строк одновременно. Такие индексы подходят для дан-
ных с небольшим количеством различных значений, которые обычно только чи-
таются. Столбец, имеющий всего три значения - Y, N и NULL, - в таблице с
миллионом строк очень хорошо подходит для создания индекса на основе бито-
вых карт. Индексы на основе битовых карт не нужно использовать в базе данных
класса ООТ из-за возможных проблем с одновременным доступом (которые мы
рассмотрим далее).
• Индексы по функции. Эти индексы на основе В*-дерева или битовых карт хранят
вычисленный результат применения функции к столбцу или столбцам строки, а
не сами данные строки. Это можно использовать для ускорения выполнения зап-
росов вида: SELECT * FROM T WHERE ФУНКЦИЯ(СТОЛБЕЦ) = НЕКОТО-
РОЕ_ЗНАЧЕНИЕ, поскольку значение ФУНКЦИЯ(СТОЛБЕЦ) уже вычисле-
но и хранится в индексе.
• Прикладные (application domain) индексы. Это индексы, которые строит и хра-
нит приложение, будь-то в базе данных Oracle или даже вне базы данных Oracle.
Надо сообщить оптимизатору, насколько избирателен индекс, насколько "доро-
гостояще" его использование, а оптимизатор решает на основе этой информации,
использовать этот индекс или нет. Текстовый индекс interMedia - пример при-
кладного индекса; он построен с помощью тех же средств, которые можно ис-
пользовать для создания собственных прикладных индексов.
• Текстовые индексы interMedia. Это встроенные в сервер Oracle специализирован-
ные индексы для обеспечения поиска ключевых слов в текстах большого объема.
Описание этих индексов будет представлено в главе 17, посвященной компонен-
ту interMedia.
Как видите, предлагается несколько типов индексов на выбор. В следующих разде-
лах я хочу представить технические детали их работы и порекомендовать, когда их ис-
пользовать. Еще раз подчеркну: мы не будем рассматривать ряд вопросов, интересую-
щих администраторов баз данных (например, механизм оперативной перестройки
индекса), а сосредоточимся на практическом использовании индексов в приложениях.
Индексы на основе В*-дерева
Цель их создания - минимизировать время поиска данных сервером Oracle. При наличии индекса по числовому столбцу, структура индекса может выглядеть так:
Блоки самого нижнего уровня в индексе, которые называют листовыми вершинами,
содержат все проиндексированные ключи и идентификаторы строк (rid на схеме), ссы-
лающиеся на соответствующие строки. Промежуточные блоки над листовыми верши-
нами называют блоками ветвления. Они используются для переходов по структуре.
Например, если необходимо найти в индексе значение 42, надо начать с вершины дере-
ва и двигаться вправо. При проверке этого блока оказывается, что необходимо перейти
к блоку в диапазоне "от 40 до 50". Этот блок оказывается листовым и ссылается на стро-
ки, содержащие число 42. Интересно отметить, что листовые блоки фактически образу-
ют двухсвязный список. Как только найдено "начало" среди листовых вершин, т.е. пер-
вое значение, очень легко просматривать значения по порядку (это называют также
просмотром диапазона по индексу, index range scan). Проходить по структуре индекса боль-
ше не нужно; мы просто переходим по листовым вершинам.
Когда имеет смысл использовать индекс на
основе В*-дерева?
Чтобы обосновать свою точку зрения, я пред-
ставлю два одинаково верных правила:
• используйте индексы на основе В*-дерева по столбцу, если предполагается вы-
бирать из таблицы по индексу лишь небольшую часть строк;
• используйте индекс на основе В*-дерева, если предполагается обработка множе-
ства строк таблицы и можно использовать индекс вместо таблицы.
Эти правила, казалось бы, противоречат друг другу, но на самом деле это не так -
просто они предназначены для двух принципиально разных случаев. Есть два способа
использовать индекс.
• Как средство доступа к строкам в таблице. Индекс читается, чтобы добраться до
строки в таблице. Так имеет смысл обращаться к очень небольшой части строк
таблицы.
• Как средство ответа на запрос. Индекс содержит достаточно информации, чтобы
дать полный ответ на запрос - к таблице вообще не придется обращаться. Ин-
декс будет использоваться как уменьшенная версия таблицы.
Индексы на основе битовых карт
Индексы на основе битовых карт создавались для хранилищ данных или сред с произ-
вольными запросами, где полный список возможных запросов к данным при реализа-
ции приложения не полностью известен. Они не походят для систем ООТ или систем,
где данные часто изменяются несколькими одновременно работающими сеансами.
Индексы на основе битовых карт - это структуры, в которых хранятся указатели на
множество строк, соответствующих одному значению ключа индекса, тогда как в струк-
туре В*-дерева количество ключей индекса обычно примерно соответствует количеству
строк. В индексе на основе битовых карт записей очень мало, и каждая из них указыва-
ет на множество строк. В индексе на основе В*-дерева обычно имеется однозначное
соответствие - запись индекса ссылается на одну строку.
Предположим, создается индекс на основе битовых карт по столбцу JOB в таблице ЕМР
Сервер Oracle будет хранить в индексе примерно следующее:
Это показывает, что в строках 8, 10 и 13 находится значение ANALYST, тогда как в
строках 4, 6 и 7 - значение MANAGER. Также понятно, что пустых строк нет (индексы
на основе битовых карт содержат записи для пустых значений - отсутствие такой запи-
си в индексе означает, что пустых строк нет). Если необходимо посчитать, в скольких
строках хранится значение MANAGER, индекс на основе битовых карт позволит сде-
лать это очень быстро.
Когда имеет смысл использовать индекс на
основе битовых карт?
Индексы на основе битовых карт больше подходят для данных с небольшим количе-
ством уникальных значений. Это данные, для которых при делении количества уникаль-
ных значений в строках на общее количество строк получается небольшое число (близ-
кое к нулю).
Индексы на основе битовых карт особенно хорошо подходят для сред с множеством
произвольных запросов, особенно, если запросы эти ссылаются произвольным образом
на много столбцов или выбирают агрегированные значения типа COUNT.
Они хорошо работают в среде с интенсивным считыванием данных, но абсолютно не подходят для ин-
тенсивных изменений. Причина в том, что одна запись индекса на основе битовых карт
ссылается на множество строк. Если сеанс изменяет проиндексированные данные, все
строки, на которые ссылается соответствующая запись индекса, по сути оказываются заб-
локированными.
Кластеры
Кластер (англ. cluster) - в СУБД Oracle Database специализированный объект базы данных, используемый для физически совместного хранения одной или нескольких таблиц, которые часто соединяются вместе вSQL-запросах. Кластеры хранят взаимосвязанные строки разных таблиц вместе в одних и тех же блоках данных, что позволяет сократить количество операций дискового ввода-вывода и улучшить время доступа длясоединений таблиц, входящих в кластер. После создания кластера в нем можно создавать таблицы. Перед тем как добавлять строки в кластеризованные таблицы необходимо создать индекс кластера.
Кластеры не влияют на проектирование модели данных приложений, их существование прозрачно для пользователей и приложений. Данные, хранящиеся в кластере, обрабатываются с помощью тех же инструкций SQL, что и данные, хранящиеся в некластеризованных таблицах.
Кластеры целесообразно использовать для хранения одной или нескольких таблиц, которые часто используются в запросах и для которых запросы часто выполняют соединение данных из нескольких связанных таблиц, либо извлекают связанные данные из одной таблицы.
Использование кластеров замедляет операции добавления, обновления, удаления строк таблицы по сравнению с хранением таблицы вне кластера со своим собственным индексом. Кроме того кластеры используют дополнительный объём дисковой памяти, поскольку каждая отдельная таблица в кластере занимает больше блоков, чем если бы она хранилась вне кластера. Поэтому перед созданием кластера следует убедиться, что планируемый выигрыш в производительности запросов превысит дополнительную затрату ресурсов на сопровождение кластера.