Почему Oracle не использует полное сканирование индекса для неуникальных индексов?

Я создал копию таблицы сотрудников в схеме HR. Затем добавил неуникальный индекс в столбец employee_id.

create table employees1 as select * from employees;
create index temp_idx on employees1(employee_id);

Затем проверил его план выполнения «выберите идентификатор сотрудника из сотрудников», он выполнил полное сканирование таблицы, и его стоимость составила 3. Однако, когда я создал уникальный индекс, он выполнил полное сканирование индекса, и стоимость была равна 1.

Насколько мне известно, способы создания уникальных и неуникальных индексов идентичны. Таким образом, количество листьев и т. Д. Должно быть одинаковым в обоих индексах. Итак, в этом случае, хотя он мог выбрать полное сканирование индекса с неуникальным индексом и снизить стоимость до 1, почему он выбрал полное сканирование таблицы и привел к худшему плану? Кстати, я не удалял и не вставлял никаких строк после создания таблицы.


person oramas    schedule 22.05.2020    source источник
comment
Это зависит от множества факторов. Сколько строк в таблице? Сколько места на диске (сколько байтов) занимает каждая строка на диске?   -  person Bohemian♦    schedule 23.05.2020
comment
@Bohemian - это ни от чего не должно зависеть. OP выбирает all строки, поэтому вопрос не в том, чтобы использовать индекс для быстрого доступа. В любом случае будет выполнено полное сканирование. Вопрос OP (немного ошибочный, как я объясняю в своем ответе): почему Oracle не считывает все значения employee_id из индекса, который во всех случаях должен быть меньше, чем вся таблица (полные строки).   -  person mathguy    schedule 23.05.2020


Ответы (1)


То, что вы сказали о плане выполнения при наличии уникального индекса, просто не соответствует действительности. (Я только что проверил на своей машине - Oracle по-прежнему выполняет полное сканирование даже с уникальным индексом.)

В этом есть смысл. Независимо от того, является ли индекс уникальным или нет, он НЕ хранит ничего, когда EMPLOYEE_ID равен NULL. С другой стороны, если были какие-либо строки с нулевым EMPLOYEE_ID, они ДОЛЖНЫ быть возвращены запросом, чтобы запрос не мог смотреть только на индекс.

Если вы хотите, чтобы Oracle выполнял сканирование индекса, вы должны либо сообщить Oracle, что столбец равен NOT NULL (это произойдет автоматически, если столбец равен primary key - возможно, вы запутались между этим и «уникальным индексом»), либо вы должны «выбрать employee_id ... ГДЕ EMPLOYEE_ID НЕ НУЛЬ ". Вы можете знать, что условие «not null» в любом случае истинно для всех строк, но Oracle не узнает об этом до тех пор, пока не прочитает все данные из таблицы - или если вы наложите ограничение not null на колонка. Если вы явно укажете, что вам нужны только ненулевые значения, Oracle знает, что может использовать индекс. (И, опять же, уникальность индекса не имеет значения!)

person mathguy    schedule 23.05.2020