Несколько индексов на один столбец - PullRequest
5 голосов
/ 09 марта 2011

При использовании Oracle существует таблица с именем User.

Столбцы: Id, FirstName, LastName

Индексы: 1. PK (Id), 2. UPPER (FirstName), 3. LOWER (FirstName), 4. Index (FirstName)

Как вы можете видеть, индексы 2, 3, 4 являются индексами в одном столбце - FirstName.

Я знаю, что это создает накладные расходы, но мой вопрос состоит в том, чтобы выбрать, как база данных будет реагировать / оптимизировать?

Например:

SELECT Id FROM пользователя u ГДЕ% '

Будет ли Oracle попадать в нужный индекс или нет?

Проблема в том, что через Hibernate это ОЧЕНЬ сильно замедляет запрос (поэтому он использует подготовленные операторы).

Спасибо.

ОБНОВЛЕНИЕ : просто для пояснения индексы 2 и 3 являются функциональными индексами.

Ответы [ 3 ]

7 голосов
/ 09 марта 2011

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

Вы должны выбрать один или другой (и, вероятно, отбросить последний тоже), и только когда-либо запрос на верхнем (илинижний)-case с чем-то вроде:

select id from user u where upper(u.firstname) like 'MIKE%'

Редактировать: посмотрите на этот пост тоже, есть некоторая интересная информация Как использовать индекс на основе функций для столбца, который содержит NULL в Oracle 10+

7 голосов
/ 09 марта 2011

В дополнение к замечанию Мата о том, что индекс 2 или 3 должен быть избыточным, поскольку вы должны выбрать один подход к поиску без учета регистра, а Ричард считает, что это будет зависеть от избирательности индекса, имейте в виду, что существуют дополнительныекасается использования предложения LIKE.

Предполагая, что вы используете переменные связывания (что звучит так, как будто вы основаны на использовании подготовленных операторов), оптимизатор должен угадать, насколько избирательно является фактическое значение связывания.собирается быть.Что-то короткое, например «S%», будет очень неселективным, поэтому оптимизатор, как правило, предпочитает сканирование таблицы.С другой стороны, более длинная строка, такая как «Smithfield-Manning%», вероятно, будет очень избирательной и будет использовать индекс 4. То, как Oracle обрабатывает эту изменчивость, будет зависеть от версии.

В Oracle 10В Oracle введена функция просмотра переменных привязки.Это означало, что в первый раз, когда Oracle анализировал запрос после перезагрузки (или после того, как план запроса устарел из общего пула), Oracle посмотрел значение привязки и решил, какой план использовать, основываясь на этом значении.Предполагая, что большинство ваших запросов выиграют от сканирования индекса, потому что пользователи обычно ищут относительно выборочные значения, это было бы хорошо, если бы первый запрос после перезагрузки имел выборочное условие.Но если вам не повезло и кто-то сделал WHERE firstname LIKE 'S%' сразу после перезагрузки, вы застряли с планом запроса сканирования таблицы, пока план запроса не был удален из общего пула.

Начиная с Oracle 11,однако оптимизатор имеет возможность адаптивного совместного использования курсора.Это означает, что оптимизатор попытается выяснить, что WHERE firstname LIKE 'S%' должен выполнить сканирование таблицы, а WHERE firstname LIKE 'Smithfield-Manning%' должен выполнить сканирование индекса и будет поддерживать несколько планов запросов для одного и того же оператора в общем пуле.Это решает большинство проблем, с которыми мы сталкивались при просмотре переменных связывания в более ранних версиях.

Но даже здесь точность оценок селективности оптимизатора, как правило, будет проблематичной для строк средней длины.Как правило, будет известно, что односимвольная строка очень слабо избирательна и что 20-символьная строка является высокоселективной, но даже с гистограммой из 256 сегментов не будет много информации о том, насколько избирательно что-то вроде WHERE firstname LIKE 'Smit%'на самом деле.Он может примерно знать, насколько селективный «Sm%» основан на гистограмме столбца, но довольно слепо догадывается, насколько избирательны следующие два символа.Поэтому нередко случается, что большинство запросов работают эффективно, но оптимизатор убежден, что WHERE firstname LIKE 'Cave%' недостаточно избирателен для использования индекса.

Предполагая, что это общий запрос,Вы можете рассмотреть возможность использования функций стабильности плана Oracle, чтобы заставить Oracle использовать конкретный план независимо от значения переменной связывания.Это может означать, что пользователям, которые вводят один символ, придется ждать еще дольше, чем они ожидали бы, потому что сканирование индекса существенно менее эффективно, чем сканирование таблицы.Но это может стоить того для других пользователей, которые ищут короткие, но достаточно отличительные фамилии.И вы можете делать такие вещи, как добавление ограничителя ROWNUM в запрос или добавление логики во внешний интерфейс, для которого требуется минимальное количество символов в поле поиска, чтобы избежать ситуаций, когда сканирование таблицы будет более эффективным.

6 голосов
/ 09 марта 2011

Может не попасть ни в один из ваших индексов, потому что вы возвращаете ID в предложении SELECT, которое не охватывается индексами.

Если индекс очень избирательный, и Oracle решает, что он все еще стоитиспользуя его для поиска «MIKE%», затем выполните поиск данных, чтобы получить столбец идентификатора, затем он может использовать 4. Index(FirstName).2 и 3 будут использоваться только в том случае, если в искомом столбце используется точная функция, определенная в индексе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...