Как может нажатие предиката во встроенном представлении замедлить выполнение запроса?

StackOverflow https://stackoverflow.com/questions/1044584

Вопрос

Я унаследовал несколько запутанный запрос, который я работаю над рефакторингом, чтобы быть производительным.

Во время этого процесса одной из вещей, которые я сделал из-за личных предпочтений, было изменение всего синтаксиса соединения ANSI-99 из операторов "inner join" и "left outer join" на предикаты в запросе.Я заметил две очень странные вещи, по поводу которых я был бы признателен за объяснение.

  1. Изменение синтаксиса соединений из "INNER JOIN ..." изменило план объяснения.Используя синтаксис ANSI 99, oracle выполнила полное сканирование таблицы по соединяемым столбцам.После изменения синтаксиса соединения он теперь выполняет выталкивание предикатов.Почему синтаксис соединения изменил бы план объяснения?
  2. Нажатие предиката на встроенное представление фактически замедлило выполнение запроса на очень значительную величину.Запрос, который выполнялся (до изменения соединений) примерно через 3 секунды.Теперь это занимает 9 секунд.Честно говоря, я довольно новичок в чтении explain plans, поэтому вполне возможно, что реструктуризация запроса замедлила его выполнение по другой причине.Но в конечном счете мой вопрос заключается в следующем:"Возможно ли, чтобы нажатие предиката на индексированные столбцы так существенно замедляло выполнение запроса?Если да, то почему?"

Спасибо за ответы и приношу свои извинения, если это не очень понятно...

Это было полезно?

Решение

Возможно ли, чтобы нажатие предиката на индексированные столбцы так существенно замедлило выполнение запроса?Если да, то почему?

Конечно, это так.

Как правило, нажатие на предикат заставляет оптимизатора выбирать NESTED LOOPS вместо того , чтобы HASH JOIN.

Это может быть медленнее, если условие не является выборочным.

Этот запрос

SELECT  *
FROM    table1, t1
        (
        SELECT  /*+ NO_PUSH_PRED */
                *
        FROM    table2 t2
        WHERE   t2.col1 = :value1
        ) t2o
WHERE   t2o.col2 = t1.col2

скорее всего, будет создана хэш-таблица поверх содержимого table1 и проверит строки, возвращаемые представлением, по этой хэш-таблице (или наоборот).

Этот запрос:

SELECT  *
FROM    table1, t1
        (
        SELECT  /*+ PUSH_PRED */
                *
        FROM    table2 t2
        WHERE   t2.col1 = :value1
        ) t2o
WHERE   t2o.col2 = t1.col2

будет использовать NESTED LOOPS и указатель на (t2.col1, t2.col2) если это определено.

Последнее более эффективно, если col2 является избирательным по table2, и менее эффективен, если это не так.

Мое обоснованное предположение заключается в том, что именно это происходит в вашем случае.

Если вы опубликуете свои запросы и планы выполнения, я, вероятно, смогу рассказать больше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top