Подтвердить что ты не робот

Использует ли Oracle оценку короткого замыкания?

У меня есть запрос Oracle, который структурирован следующим образом:

SELECT   *
FROM     table
WHERE    X='true' OR
         Y IN (complicated subquery)

Если Oracle увидит, что X равно "true", он все равно попытается оценить часть Y IN (подзапрос) в предложении WHERE? Кроме того, в таком заявлении, как подзапрос будет выполняться несколько раз для каждой записи в таблице? Будет ли я лучше с чем-то вроде:

WITH subQ as (complicated subquery)
SELECT   *
FROM     table
WHERE    X='true' OR
         Y IN (SELECT id FROM subQ)
4b9b3361

Ответ 1

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

При этом, если оптимизатор может определить во время компиляции, что предикат всегда будет оценивать до TRUE или FALSE, оптимизатор должен просто рассматривать это как константу. Так, если, например, существует ограничение на таблицу, которое предотвращает X от когда-либо имеющего значение "true", оптимизатор не должен вообще оценивать второй предикат (хотя разные версии оптимизатора будут иметь разные возможности чтобы обнаружить, что что-то является константой во время компиляции).

Что касается второй части вашего вопроса, не видя планов запросов, это очень сложно сказать. Оптимизатор Oracle, как правило, очень хорош в преобразовании запросов из одной формы в другую, если есть более эффективные способы ее оценки. В общем случае, однако, если subQ вернет относительно большое количество строк по сравнению с table, может быть более эффективным структурировать запрос как EXISTS, а не как IN.

Ответ 2

Предостережение: Oracle не является моей основной областью знаний.

Оптимизатор, основанный на затратах, должен знать, что стоимость X = 'true' меньше, чем подзапрос, поэтому он, скорее всего, сначала оценит более простой вариант. Но условия AND и OR в SQL не являются короткозамкнутыми, как && и || находятся в C и его производных.

Подзапрос может быть одной из двух форм: коррелированный и некоррелированный.

  • Корректированный подзапрос должен выполняться много раз (поэтому он опасен для производительности), потому что корреляция означает, что результат суб-запроса каким-то образом зависит от строки "в настоящее время оценивается" ).
  • Некорректированный подзапрос будет выполняться только один раз.

Пример коррелированного подзапроса:

SELECT *
  FROM Table1
 WHERE X = 'true'
    OR Y IN (SELECT Z FROM Table2 WHERE Table2.A = Table1.B)

Пример некоррелированного подзапроса:

SELECT *
  FROM Table1
 WHERE X = 'true'
    OR Y IN (SELECT Z FROM Table2 WHERE Table2.A > 13)

Ответ 3

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

Например:

select * from table 1
where case when X = 'true' then 1
           when Y in (select ....)   then 1
      end  = 1

Если X является "истинным", тогда выражение case оценивается в 1, второе "когда" пропускается и условие оценивается как "ИСТИНА". Если X не является "истинным", тогда выполняется условие IN.