Привязка переменных приводит к полному сканированию таблицы в Oracle - PullRequest
0 голосов
/ 30 апреля 2018

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

Это ожидаемое поведение от Oracle? Есть ли способ запретить Oracle сканировать полную таблицу?

Запрос сканирует полную таблицу при использовании переменных связывания:

The query is scanning the full table when bind variables are used

Стоимость запроса значительно снижается благодаря фактическим переменным:

The query cost reduces significantly with actual variables

1 Ответ

0 голосов
/ 30 апреля 2018

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

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

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

Это ожидаемое поведение от Oracle?

Теперь, когда вы поймете это, вы увидите, что ответ на этот вопрос да . Оптимизатор принимает лучшее решение, которое он может, используя информацию, которую мы ему даем. Когда мы предоставляем жесткие ценности, это может быть очень умным. Когда мы предоставляем расплывчатые данные, он должен догадаться; иногда его догадки не те, которые мы ожидали.

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

Есть ли способ запретить Oracle сканировать полную таблицу?

Если вы можете исправить размер страницы, удалив, таким образом, параметр :a2, это позволит оптимизатору составить гораздо более точный план. В качестве альтернативы, если вам нужно изменить размер страницы в небольшом диапазоне (скажем, от 10 до 100), вы можете попробовать подсказку /*+ cardinality (100) */ в запросе; при условии, что значение мощности находится в правильном порядке, оно не должно быть точным значением.

Как и во всех вопросах производительности, дьявол кроется в специфике. Таким образом, вам нужно сравнить различные изменения производительности и выбрать наиболее подходящий для вас вариант (ы) использования.

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