Индекс не привыкает - PullRequest
       10

Индекс не привыкает

0 голосов
/ 02 сентября 2018

Это отрывок из книги Тома Кайта.

"Мы используем запрос SELECT COUNT(*) FROM T (или что-то подобное) и у нас есть индекс B * Tree в таблице T. Однако оптимизатор заполнен сканирование таблицы, а не подсчет (гораздо меньшего) индекса записей. В этом случае индекс, вероятно, находится на наборе столбцов, которые может содержать нули. Поскольку полностью нулевая запись индекса никогда не будет сделано, количество строк в индексе не будет количеством строк в стол. Здесь оптимизатор делает правильные вещи - он получит неправильный ответ, если он использовал индекс для подсчета строк. "

Насколько я знаю, индексы проявляются, когда мы используем предложение WHERE. Почему индекс входит в вышеупомянутый сценарий? Прежде чем противостоять ему, я хотел узнать факты.

Ответы [ 3 ]

0 голосов
/ 02 сентября 2018

База данных Oracle не хранит значения NULL в индексе B-дерева, см. документацию

База данных Oracle не индексирует строки таблицы, в которых все ключевые столбцы null, кроме растровых индексов или когда значение столбца ключа кластера является нулевым.

Из-за этого, если индекс был создан для столбца, который может содержать нулевые значения , база данных не может использовать этот индекс в запросе, подобном: SELECT COUNT(*) FROM T. Даже если столбец не содержит NULL, оптимизатор не узнает об этом, если столбец не помечен как NOT NULL.


Согласно документации - БЫСТРЫЙ ПОЛНЫЙ ИНДЕКС СКАН

Быстрое полное индексное сканирование

Быстрое полное сканирование индекса - это полное сканирование индекса в который база данных обращается к данным в самом индексе без доступ к таблице, и база данных считывает индексные блоки в нет конкретный заказ.

Быстрое полное сканирование индекса является альтернативой полному сканированию таблицы, когда выполняются оба следующих условия:

Индекс должен содержать все столбцы, необходимые для запроса.

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

  • Ограничение NOT NULL

  • Предикат, примененный к столбцу, который предотвращает появление нулей учитывается в наборе результатов запроса

Если вы знаете, что индексированный столбец не может содержать значения NULL, пометьте этот столбец как NOT NULL, используя ALTER TABLE table_name MODIFY column_name column_type NOT NULL;, и база данных будет использовать этот индекс в запросе: SELECT COUNT(*) FROM T

Если столбец может иметь нулевые значения и не может быть помечен как NOT NULL, используйте решение из ответа @Gordon Linoff.

0 голосов
/ 02 сентября 2018

"Насколько я знаю, индексы появляются на картинке, когда вы использовали предложение where."

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

Подсчет строк один. Для подсчета количества строк в таблице Oracle фактически должен считать каждую строку (потому что статистика может быть недостаточно свежей), что означает буквальное чтение каждого блока хранения и подсчет строк в каждом блоке. Потенциально это много читает.

Однако в индексе столбца NOT NULL также есть запись для каждой строки таблицы. Индексы намного меньше таблиц (обычно только один столбец), поэтому в блоке индекса содержится гораздо больше записей, чем в блоке таблицы. Следовательно, Oracle должен прочитать намного меньше блоков индекса, чтобы получить количество строк, чем требуется для сканирования таблицы. Чтение меньшего количества блоков быстрее, чем чтение большего количества блоков.

Это не так, если таблица имеет индексы только для столбцов, допускающих значение NULL. Oracle не индексирует нулевые значения (если индекс не является составным индексом и не заполнен хотя бы один столбец), поэтому количество записей в индексе не может гарантировать фактическое количество строк таблицы.

Другим распространенным вариантом использования для чтения индексов является выполнение инструкции SELECT, когда все столбцы в проекции находятся в одном индексе, и этот индекс также обслуживает любые условия WHERE.

0 голосов
/ 02 сентября 2018

Вы можете принудительно индексировать значения NULL, включив в индекс константу:

create index t_table_col on t(col, 0);

1 - это константное выражение, которое никогда не будет NULL.

...