
- •3. Создание индексов и ограничений для базы данных
- •3.1. Индексы в базах данных
- •3.2. Создание и удаление индекса
- •3.3. Типы индексов
- •Индексы в*-дерева
- •Битовые индексы
- •3.4. Обеспечение целостности данных с помощью ограничений
- •Ограничение not null
- •Ограничение unique
- •Ограничение check
- •Разрешение и запрещение существующих ограничений
- •Изменение и удаление существующих ограничений
- •Место определения ограничений
- •3.5. Связи между таблицами
- •Использование ограничений для установления связей между таблицами
- •Многотабличные запросы
- •Внешние соединения
3. Создание индексов и ограничений для базы данных
3.1. Индексы в базах данных
Принцип индексирования широко применяется при работе с таблицами базы данных. Когда таблица содержит большое число записей, ее полный просмотр с целью поиска определенных записей может занять у Oracle (как и у любой другой СУБД) много времени — сравните это с перелистыванием всей книги при поиске страниц, где обсуждается определенная тема. Oracle позволяет создавать вторую, скрытую таблицу, содержащую один или несколько важных столбцов из главной таблицы вместе с указателями на строки основной таблицы. В данном случае вместо номеров страниц указателями являются номера строк. Эту скрытую таблицу принято называть индексом. Просматривая индекс, Oracle может узнать, какие строки содержат запрашиваемые данные (при условии, что эти данные находятся в столбцах, составляющих индекс). Поскольку индекс намного меньше таблицы, на которую он ссылается (подобно тому как книжный индекс намного меньше полного текста книги), поиск данных в таблице с индексом будет выполняться, существенно быстрее, чем в таблице без индекса.
На рис. 3.1 показано, как выглядел бы стандартный индекс для таблицы PERSON. В данном случае таблица проиндексирована по столбцу PERSON_CODE. Важно, что индекс отсортирован по PERSON_CODE, хотя таблица хранит записи в последовательности их ввода.
Таблица PERSON Индекс PERSON_CODE
PERSON_CODE |
FIRST_NAME |
LAST_NAME |
HIRE_DATE |
|
PERSON_CODE |
ROWNUM |
СА |
Chariene |
Adas |
01-Feb-02 |
|
BB |
3 |
GA |
Gary |
Anderson |
15-Feb-02 |
|
CA |
1 |
ВВ |
Bobby |
Barkenhagen |
01-Feb-02 |
|
GA |
2 |
LВ |
Laren |
Baxter |
01-Feb-02 |
|
LB |
4 |
Рис. 3.1. Таблица с одним индексом
Записи индекса всегда сортируются по тем столбцам, которые он содержит. Столбец ROWNUM, входящий в индекс, отслеживает положение каждой строки в исходной таблице.
На рис. 3.2 показана аналогичная связь между таблицей PURCHASE и двумя индексами. Таблица может иметь более одного индекса, и таблица PURCHASE служит хорошей иллюстрацией этому. Она содержит как минимум два столбца, являющихся потенциальными кандидатами на индексирование: столбец товаров и столбец продавцов. Весьма вероятно, что запросы к таблице часто будут основываться на названии товара, и не менее вероятно, что другие запросы будут основываться на имени продавца. Создавая отдельный индекс для каждого из этих столбцов, вы получаете такое же увеличение скорости поиска, как и в случае таблицы с одним индексом, но теперь оно будет иметь место как при поиске по названию товара, так и при поиске по имени продавца.
Таблица PURCHASE Индекс PRODUCT_NAME Индекс SALESPERSON
PRODUCT_NAME |
QUANTITY |
PURCHASE_DATE |
SALES PERSON |
|
PERSON_CODE |
ROWNUM |
|
SALESPERSON |
ROW NUM |
Small Widget |
1 |
14-Jul-03 |
CA |
|
Chrome Phoobar |
3 |
|
BB |
2 |
Medium Wodget |
75 |
14-Jul-03 |
BB |
|
Medium Wodget |
2 |
|
CA |
1 |
Chrome Phoobar |
2 |
14-Jul-03 |
GA |
|
Medium Wodget |
5 |
|
CA |
6 |
Small Widget |
8 |
14-Jul-03 |
GA |
|
Round Snaphoo |
6 |
|
GA |
3 |
Medium Wodget |
20 |
14-JuMB |
LB |
|
Small Widget |
1 |
|
GA |
4 |
Round Snaphoo |
5 |
14-Jul-03 |
CA |
|
Small Widget |
4 |
|
LB |
5 |
Рис. 3.2. Таблица с индексами по двум разным столбцам
После того как создан индекс, Oracle автоматически поддерживает его синхронизацию с таблицей. Любые операции вставки, обновления или удаления над этой таблицей будут автоматически изменять ее индекс, и любая команда SELECT будет выполняться с привлечением индекса, если он содержит требуемые столбцы. Добавление или удаление индексов не влияет на операции с таблицей — любая использовавшая ее программа по-прежнему будет работать, хотя и более медленно. В случае удаления таблицы все ассоциированные с ней индексы также будут удалены, поскольку без таблицы индекс бесполезен.
Индексы уменьшают время отклика команд, выполнение которых требует считывания содержимого таблицы. Это означает, что все команды SELECT, UPDATE и DELETE будут работать быстрее, если таблица имеет подходящий индекс.
Добавление индексов к таблице не ускоряет ввод данных командами INSERT; фактически это дает обратный эффект, замедляя вставку. Поскольку индекс тоже является таблицей, то когда добавляется запись к проиндексированной таблице, Oracle должен добавить запись и к самой таблице, и к ее индексу, т.е. выполнить две вставки для каждой записи. В результате добавление индекса к таблице вызовет более чем двукратное увеличение времени вставки (собственно две вставки плюс небольшое дополнительное время на их координацию). Добавление двух индексов замедлит операцию вставки в три раза, трех индексов — в четыре раза, и т.д.
Таким образом, использование индексов — это компромисс. Они замедляют ввод данных, но ускоряют их считывание. Следовательно, индексирование таблиц нежелательно в тех приложениях, где ввод данных должен происходить как можно быстрее. Например, в системе, обслуживающей сеть розничных магазинов, от кассовых терминалов требуется максимальная скорость выполнения транзакций. В этом случае индексирование таблицы транзакций будет ошибкой, поскольку приведет к замедлению ввода данных. С другой стороны, в той же самой фирме могут работать специалисты, которым нужно выполнять запросы, анализирующие транзакции, а эти запросы сильно выиграют от наличия правильно индексированных таблиц. Как удовлетворить этим противоречивым требованиям? Во многих системах данные о транзакциях каждую ночь автоматически копируются из рабочих таблиц во вспомогательные индексированные таблицы, которые на следующий день используются для анализа. Вставка данных в индексированную таблицу занимает намного больше времени, чем вставка в таблицу транзакций, не имеющую индексов, но это никого не волнует, поскольку магазины закрыты, покупателей нет, а вся работа выполняется компьютерами.
Чем больше таблица, тем больший выигрыш можно получить от ее индексирования. В качестве примера можно взять таблицу с миллионом записей. В табл. 3.1 показано, сколько времени занимали различные операции DML при наличии и отсутствии индекса. Первая строка содержит статистику по оператору SELECT, а последующие строки демонстрируют влияние индекса на команды UPDATE и DELETE.
Таблица 3.1
Время (секунды) выполнения операций DML при наличии и отсутствии индекса
-
Операция
Без индекса
С индексом
Увеличение скорости
SELECT (50 записей)
18.9
0.6
в 31.5 раза
UPDATE (50 записей)
19.7
0.5
в 39.4 раза
DELETE (50 записей)
19.6
0.06
в 326.7 раза