Спрятать колонку

индекс

Oracle. Индексы и Null

Вопросы, связанные с NULL значениями, весьма интересны в oracle. Пока не столкнешься на практике - не узнаешь, в чем подвох с ними.

Возьмем известный и проверяемый факт: индексы не хранят null значения. Что дает нам это на практике?
Рассмотрим следующую ситуацию. Возможно, что этот пример можно считать просто наглядным, однако, он покажет, насколько важно знать на этапе проектирования, какие запросы будут идти к таблице.

Есть таблица, в которой лежат и "основные данные" и те, для которых необходима "предобработка". Чтобы не плодить сущностей, решили вместо PK сделать UK и необработанные записи хранить в таблице со значением NULL. Казалось бы, проблемы нет.

Приведу пример:

Создадим таблицу с уникальным ключом по полю, заполним ее данными, а в конце соберем статистику по индексу.

CREATE TABLE select_null(
  id number
);
 
CREATE UNIQUE INDEX X_ID_SELECT_NULL ON select_null(id);
 
INSERT INTO select_null(id) VALUES(1);
INSERT INTO select_null(id) VALUES(2);
INSERT INTO select_null(id) VALUES(NULL);
INSERT INTO select_null(id) VALUES(NULL);
INSERT INTO select_null(id) VALUES(NULL);
INSERT INTO select_null(id) VALUES(3);
 
commit;
 
ANALYZE INDEX X_ID_SELECT_NULL COMPUTE STATISTICS;

Теперь перед нами стоит тривиальная задача: вычитать все данные, которые нуждаются в предобработке, т.е. где id = NULL. Это очень просто:

SELECT * FROM select_null
WHERE id IS NULL

Ура, мы справились. Или же нет? Взглянем на план выполнения запроса:

SELECT STATEMENT  ALL_ROWSCost: 3  Bytes: 39  Cardinality: 3  	
	1 TABLE ACCESS FULL TABLE USR.SELECT_NULL Cost: 3  Bytes: 39  Cardinality: 3  

Да в ней же есть FULL SCAN. Откуда взялся он!? Ответ прост: как мы знаем, в индексе не содержаться NULL значения. Индекс будет проигнорирован и не помогут тут ни хинты, ни RBO.

>> Читать далее
RSS-материал

Наверх