Oracle: Создание индексов связанных с ограничением целостности. Обзор типов индексов Oracle, MySQL, PostgreSQL, MS SQL Уникальный индекс, UNIQUE INDEX

Создание индекса является методом увеличения производительности работы СУБД при извлечению записей. В индексе создается запись для каждого значения, которое появляется в индексируемом столбце. По умочанию, Oracle создает индексы типа .

Создание Индекса

Синтаксис создания индекса:


ON table_name (column1, column2, . column_n)
[ COMPUTE STATISTICS ];

Параметр UNIQUE указывает, что комбинация значений в индексируемых столбцах таблицы должна быть уникальной.

Параметр COMPUTE STATISTICS командует Oracle-у собирать статистику в процессе создания индекса . Эта статистика в последствии используется оптимизатором при выборе «plan of execution» в процессе выполнения SQL-запроса.

Например:

CREATE INDEX supplier_idx
ON supplier (supplier_name);

В этом примере, мы создали индекс на таблице supplier с именем supplier_idx. Он содержит только одно поле – supplier_name.

Также мы можем создать индексы с большим, чем одно, количеством полей, как в следующем примере:

CREATE INDEX supplier_idx
ON supplier (supplier_name, city);

Мы также можем включить сбор статистики создав индекс следующим образом:

CREATE INDEX supplier_idx
ON supplier (supplier_name, city)
COMPUTE STATISTICS;

Создание Индексов на основе функций

В Oracle, вы не ограничены созданием индексов только на столбцах таблиц. Вы можете создавать индексы основанные на функциях.

Синтаксис создания индекса на основе функции:

CREATE INDEX index_name
ON table_name (function1, function2, . function_n)
[ COMPUTE STATISTICS ];

Например:

CREATE INDEX supplier_idx
ON supplier (UPPER(supplier_name));

В этом примере, мы создали индекс основанный на функции uppercase примененной к полю supplier_name .

Однако, чтобы быть уверенным, что Oracle оптимизатор использует этот индекс, когда выполняет ваши SQL-запросы, убедитесь в
том, что значение UPPER(supplier_name) не возращает NULL. Чтобы это проверить, добавьте выражение UPPER(supplier_name) IS NOT NULL в оператор WHERE следующим образом:

SELECT supplier_id, supplier_name, UPPER(supplier_name)
FROM supplier
WHERE UPPER(supplier_name) IS NOT NULL
ORDER BY UPPER(supplier_name);

Переименование Индекса

Синтаксис переименования индекса:

ALTER INDEX index_name
RENAME TO new_index_name;

Например:

ALTER INDEX supplier_idx
RENAME TO supplier_index_name;

В этом примере мы переименовали индекс supplier_idx в supplier_index_name .

Сбор статистики по Индексу

Если вы хотите включить сбор статистики по индексу после его создания или хотите обновить статистику, воспользуйтесь командой
ALTER INDEX.

Синтаксис подключения сбора статистики по индексу:

ALTER INDEX index_name
REBUILD COMPUTE STATISTICS;

Например:

ALTER INDEX supplier_idx
REBUILD COMPUTE STATISTICS;

В этом примере, мы собираем статистику для индекса supplier_idx.

Удаление Индекса (Drop an Index)

Синтаксис удаления индекса:

Например:

DROP INDEX supplier_idx;

В этом примере, мы удалили индекс supplier_idx.

Oracle обеспечивает выполнение ограничения целостности UNIQUE или PRIMARY KEY для таблицы, создавая уникальный индекс для уникального или первичного ключа. Этот индекс создается автоматически, когда включается ограничение целостности. Когда выполняется CREATE TABLE или ALTER TABLE, для создания индекса не надо предпринимать никаких действий, но при желании можно указать предложение USING INDEX, чтобы контролировать его создание.

Чтобы включить ограничение целостности UNIQUE или PRIMARY KEY, создавая таким образом связанный с ним индекс, владелец таблицы должен иметь квоту табличного пространства, где будет храниться этот индекс, или системную привилегию UNLIMITED TABLESPACE. Индекс связанный с ограничением целостности всегда получает имя этого ограничения, если вы не укажете иное.

Параметры хранения для индексов связанных с ограничением целостности UNIQUE или PRIMARY KEY, можно устанавливать с помощью предложения USING INDEX.

Следующий пример CREATE TABLE включает ограничение целостности PRIMARY KEY и задает параметры хранения связанного с ним индекса:

CREATE TABLE ALL_ORACLE_USERS ( ID NUMBER (5 ) PRIMARY KEY . . . LOCKED INTEGER ) ENABLE PRIMARY KEY USING INDEX TABLESPACE ALL_ORACLE_IDX_TBS PCTFREE 0 ;

Если требуется более явное управление индексами, связанными с ограничением целостности UNIQUE или PRIMARY KEY, то Oracle позволяет:

  • Указывать существующий индекс, который Oracle должен использовать для обеспечения выполнения ограничения целостности.
  • Указывать оператор создания индекса, который Oracle должен использовать, чтобы создать индекс и обеспечить выполнение ограничения целостности.
Эти возможности задаются с помощью предложения USING INDEX. Это продемонстрировано в следующих примерах:

CREATE TABLE TEST ( COL1 INT PRIMARY KEY USING INDEX (CREATE INDEX TEST_IDX ON TEST (COL1 ) ) ) ; CREATE TABLE TEST ( COL1 INT , COL2 INT , CONSTRAINT TESTU1 UNIQUE (COL1 , COL2 ) USING INDEX (CREATE UNIQUE INDEX TEST_IDX ON TEST (COL1 , COL2 ) ) , CONSTRAINT TESTU2 UNIQUE (COL2 , COL1 ) USING INDEX TEST_IDX) ; CREATE TABLE TEST ( COL1 INT , COL2 INT ) ; CREATE INDEX TEST_IDX ON TEST (COL1 , COL2 ) ; ALTER TABLE TEST ADD CONSTRAINT TEST_CON PRIMARY KEY (COL1 ) USING INDEX TEST_IDX;

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

Индексы создаются для обеспечения уникальности столбцов, упроще­ния сортировки и быстрого поиска данных по значениям столбцов. Столб­цы, которые часто фигурируют в условиях равенства в предложениях WHERE, являются хорошими кандидатами на создание индекса. Условия равенства могут относиться к одной таблице или же к соединению. Эти два случая представлены в следующих примерах:

SELECT *
FROM MyTable
WHERE Columnl =100;

SELECT *
FROM MyTable1, MyTable2
WHERE MyTable1.Columnl = MyTable2.Column2;

Если подобные операторы выполняются часто, то столбцы Columnl и Column2 являются перспективными кандидатами на создание индексов.

Следующий оператор создает индекс по столбцу Name таблицы CUSTOMER:

CREATE INDEX CustNameldx ON CUSTOMER(Name);

Индексу дано имя CustNameldx. И здесь имя не играет особой роли для Oracle. Чтобы создать уникальный индекс, перед ключевым словом INDEX нужно вставить ключевое слово UNIQUE. Например, чтобы га­рантировать, что ни одно произведение не будет записано дважды в таб­лицу WORK, можно создать уникальный индекс по столбцам (Title, Сору, ArtistID), как показано ниже:

CREATE UNIQUE INDEX WorkUniquelndex ON W0RK(Title, Copy, ArtistID);

В одном из комментариев здесь была просьба рассказать подробнее об индексах, и так как, в рунете практически нет сводных данных о поддерживаемых индексах различных СУБД, в данном обзоре я рассмотрю, какие типы индексов поддерживаются в наиболее популярных СУБД

B-Tree

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

Так как большинство, наверное, их хорошо знает(или могут прочесть о них например, ), то единственное, что, пожалуй, следует здесь отметить, это то, что данный тип индекса оптимален для множества с хорошим распределением значений и высокой мощностью(cardinality-количество уникальных значений).

Пространственные индексы

В данный момент все данные СУБД имеют пространственные типы данных и функции для работы с ними, для Oracle - это множество типов и функций в схеме MDSYS, для PostgreSQL - point, line, lseg, polygon, box, path, polygon, circle, в MySQL - geometry, point, linestring, polygon, multipoint, multilinestring, multipolygon, geometrycollection, MS SQL - Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection.
В схеме работы пространственных запросов обычно выделяют две стадии или две ступени фильтрации. СУБД, обладающие слабой пространственной поддержкой, отрабатывают только первую ступень (грубая фильтрация, MySQL). Как правило, на этой стадии используется приближенное, аппроксимированное представление объектов. Самый распространенный тип аппроксимации – минимальный ограничивающий прямоугольник (MBR – Minimum Bounding Rectangle) .
Для пространственных типов данных существуют особые методы индексирования на основе R-деревьев(R-Tree index) и сеток(Grid-based Spatial index).
Spatial grid
Spatial grid(пространственная сетка) index – это древовидная структура, подобная B-дереву, но используется для организации доступа к пространственным(Spatial) данным, то есть для индексации многомерной информации, такой, например, как географические данные с двумерными координатами(широтой и долготой). В этой структуре узлами дерева выступают ячейки пространства. Например, для двухмерного пространства: сначала вся родительская площадь будет разбита на сетку строго определенного разрешения, затем каждая ячейка сетки, в которой количество объектов превышает установленный максимум объектов в ячейке, будет разбита на подсетку следующего уровня. Этот процесс будет продолжаться до тех пор, пока не будет достигнут максимум вложенности (если установлен), или пока все не будет разделено до ячеек, не превышающих максимум объектов.

В случае трехмерного или многомерного пространства это будут прямоугольные параллелепипеды (кубоиды) или параллелотопы.

Quadtree
Quadtree – это подвид Grid-based Spatial index, в котором в родительской ячейке всегда 4 потомка и разрешение сетки варьируется в зависимости от характера или сложности данных.
R-Tree
R-Tree (Regions Tree) – это тоже древовидная структура данных подобная Spatial Grid, предложенная в 1984 году Антонином Гуттманом. Эта структура данных тоже разбивает пространство на множество иерархически вложенных ячеек, но которые, в отличие от Spatial Grid, не обязаны полностью покрывать родительскую ячейку и могут пересекаться.
Для расщепления переполненных вершин могут применяться различные алгоритмы, что порождает деление R-деревьев на подтипы: с квадратичной и линейной сложностью(Гуттман, конечно, описал и с экспоненциальной сложностью - Exhaustive Search, но он, естественно, нигде не используется).
Квадратичный подтип заключается в разбиении на два прямоугольника с минимальной площадью, покрывающие все объекты. Линейный – в разбиении по максимальной удаленности.

HASH

Hash-индексы были предложены Артуром Фуллером, и предполагают хранение не самих значений, а их хэшей, благодаря чему уменьшается размер(а, соответственно, и увеличивается скорость их обработки) индексов из больших полей. Таким образом, при запросах с использованием HASH-индексов, сравниваться будут не искомое со значения поля, а хэш от искомого значения с хэшами полей.
Из-за нелинейнойсти хэш-функций данный индекс нельзя сортировать по значению, что приводит к невозможности использования в сравнениях больше/меньше и «is null». Кроме того, так как хэши не уникальны, то для совпадающих хэшей применяются методы разрешения коллизий.

Bitmap

Bitmap index – метод битовых индексов заключается в создании отдельных битовых карт (последовательность 0 и 1) для каждого возможного значения столбца, где каждому биту соответствует строка с индексируемым значением, а его значение равное 1 означает, что запись, соответствующая позиции бита содержит индексируемое значение для данного столбца или свойства.

Reverse index

Reverse index – это тоже B-tree индекс но с реверсированным ключом, используемый в основном для монотонно возрастающих значений(например, автоинкрементный идентификатор) в OLTP системах с целью снятия конкуренции за последний листовой блок индекса, т.к. благодаря переворачиванию значения две соседние записи индекса попадают в разные блоки индекса. Он не может использоваться для диапазонного поиска.
Пример:
Как видите, значение в индексе изменяется намного больше, чем само значение в таблице, и поэтому в структуре b-tree, они попадут в разные блоки.

Inverted index

Инвертированный индекс – это полнотекстовый индекс, хранящий для каждого лексемы ключей отсортированный список адресов записей таблицы, которые содержат данный ключ.

В упрощенном виде это будет выглядеть так:

Partial index

Partial index - это индекс, построенный на части таблицы, удовлетворяющей определенному условию самого индекса. Данный индекс создан для уменьшения размера индекса.

Function-based index

Самим же гибким типом индексов являются функциональные индексы, то есть индексы, ключи которых хранят результат пользовательских функций. Функциональные индексы часто строятся для полей, значения которых проходят предварительную обработку перед сравнением в команде SQL. Например, при сравнении строковых данных без учета регистра символов часто используется функция UPPER. Создание функционального индекса с функцией UPPER улучшает эффективность таких сравнений.
Кроме того, функциональный индекс может помочь реализовать любой другой отсутствующий тип индексов данной СУБД(кроме, пожалуй, битового индекса, например, Hash для Oracle)

Сводная таблица типов индексов

MySQL PostgreSQL MS SQL Oracle
B-Tree index Есть Есть Есть Есть
Поддерживаемые пространственные индексы(Spatial indexes) R-Tree с квадратичным разбиением Rtree_GiST(используется линейное разбиение) 4-х уровневый Grid-based spatial index (отдельные для географических и геодезических данных) R-Tree c квадратичным разбиением; Quadtree
Hash index Только в таблицах типа Memory Есть Нет Нет
Bitmap index Нет Есть Нет Есть
Reverse index Нет Нет Нет Есть
Inverted index Есть Есть Есть Есть
Partial index Нет Есть Есть Нет
Function based index Нет Есть Есть Есть

Стоит упомянуть, что в PostgreSQL GiST позволяет создать для любого собственного типа данных индекс основанный на R-Tree. Для этого нужно реализовать все 7 функций механизма R-Tree.
Дополнительно можно прочитать здесь:

This Oracle tutorial explains how to create, rename and drop indexes in Oracle with syntax and examples.

What is an Index in Oracle?

An index is a performance-tuning method of allowing faster retrieval of records. An index creates an entry for each value that appears in the indexed columns. By default, Oracle creates B-tree indexes.

Create an Index

Syntax

The syntax for creating an index in Oracle/PLSQL is:

CREATE INDEX index_name ON table_name (column1, column2, ... column_n) [ COMPUTE STATISTICS ]; UNIQUE It indicates that the combination of values in the indexed columns must be unique. index_name The name to assign to the index. table_name The name of the table in which to create the index. column1, column2, ... column_n The columns to use in the index. COMPUTE STATISTICS It tells Oracle to collect statistics during the creation of the index. The statistics are then used by the optimizer to choose a "plan of execution" when SQL statements are executed.

Example

Let"s look at an example of how to create an index in Oracle/PLSQL.

CREATE INDEX supplier_idx ON supplier (supplier_name);

In this example, we"ve created an index on the supplier table called supplier_idx. It consists of only one field - the supplier_name field.

We could also create an index with more than one field as in the example below:

CREATE INDEX supplier_idx ON supplier (supplier_name, city);

We could also choose to collect statistics upon creation of the index as follows:

CREATE INDEX supplier_idx ON supplier (supplier_name, city) COMPUTE STATISTICS;

Create a Function-Based Index

In Oracle, you are not restricted to creating indexes on only columns. You can create function-based indexes.

Syntax

The syntax for creating a function-based index in Oracle/PLSQL is:

CREATE INDEX index_name ON table_name (function1, function2, ... function_n) [ COMPUTE STATISTICS ]; UNIQUE It indicates that the combination of values in the indexed columns must be unique. index_name The name to assign to the index. table_name The name of the table in which to create the index. function1, function2, ... function_n The functions to use in the index. COMPUTE STATISTICS It tells Oracle to collect statistics during the creation of the index. The statistics are then used by the optimizer to choose a "plan of execution" when SQL statements are executed.

Example

Let"s look at an example of how to create a function-based index in Oracle/PLSQL.

CREATE INDEX supplier_idx ON supplier (UPPER(supplier_name));

In this example, we"ve created an index based on the uppercase evaluation of the supplier_name field.

However, to be sure that the Oracle optimizer uses this index when executing your SQL statements, be sure that UPPER(supplier_name) does not evaluate to a NULL value. To ensure this, add UPPER(supplier_name) IS NOT NULL to your WHERE clause as follows:

SELECT supplier_id, supplier_name, UPPER(supplier_name) FROM supplier WHERE UPPER(supplier_name) IS NOT NULL ORDER BY UPPER(supplier_name);

Rename an Index

Syntax

The syntax for renaming an index in Oracle/PLSQL is:

ALTER INDEX index_name RENAME TO new_index_name; index_name The name of the index that you wish to rename. new_index_name The new name to assign to the index.

Example

Let"s look at an example of how to rename an index in Oracle/PLSQL.

ALTER INDEX supplier_idx RENAME TO supplier_index_name;

In this example, we"re renaming the index called supplier_idx to supplier_index_name .

Collect Statistics on an Index

If you forgot to collect statistics on the index when you first created it or you want to update the statistics, you can always use the ALTER INDEX command to collect statistics at a later date.

Syntax

The syntax for collecting statistics on an index in Oracle/PLSQL is:

ALTER INDEX index_name REBUILD COMPUTE STATISTICS; index_name The index in which to collect statistics.

Example

Let"s look at an example of how to collect statistics for an index in Oracle/PLSQL.

ALTER INDEX supplier_idx REBUILD COMPUTE STATISTICS;

In this example, we"re collecting statistics for the index called supplier_idx.

Drop an Index

Syntax

The syntax for dropping an index in Oracle/PLSQL is:

DROP INDEX index_name; index_name The name of the index to drop.

Example

Let"s look at an example of how to drop an index in Oracle/PLSQL.

DROP INDEX supplier_idx;

In this example, we"re dropping an index called supplier_idx.