Смешивание переменных связывания с литералами в Oracle - PullRequest
2 голосов
/ 20 декабря 2011

Этот вопрос может лучше подойти для сайта обмена стеками БД, но я не был уверен.

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

select *
from report
where report.name = :1
and report.enabled = '1'

Я мог бы добавить это, чтобы сказать:

select *
from report
where report.name = :1
and report.enabled = :2

Я бы просто внес изменение, но процесс на самом деле сделать это в программном обеспечении и увидеть разницуэто делает несколько длинным и утомительным.Кто-нибудь знает, влияет ли смешивание литералов (как в первом примере) на эффективность оптимизатора, хотя они постоянно одинаковы?

Заранее спасибо.

Ответы [ 4 ]

7 голосов
/ 20 декабря 2011

Я не совсем уверен, что вы подразумеваете под I learned that using bind variables makes the parser not work as hard, но я угадаю ...

Собираете ли вы строки SQL в своем клиенте и отправляете их в базу данных oracle для выполнения?

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

Это означает, что движку не требуется повторная компиляция собственного SQL, и он может повторно использовать план уже (потенциально) в кэше.

Без параметризации и с другими значениями для «имени» механизм будет рассматривать запросы как совершенно разные и не замечать сходства.Это приведет к компиляции SQL, если только точная такая же строка уже находится в кэше.

Если ваши запросы, однако, всегда имеют report.enabled = 1, нет необходимости параметризовать эту часть запроса.Поскольку он статичен, то, если вы не используете параметр, он не будет выглядеть как другой запрос и не будет вызывать его повторную компиляцию.

Напротив, вы можете сэкономитьв зависимости от индексов, статистики ваших данных и т. д. Если, например, 99% ваших данных имеют значение «enabled = 1», вы можете получить другой план, тогда как 1% ваших данных будет «enabled = 1».Но механизм будет оптимизировать только для «enabled = 1» в запросе, где известно , что искомое значение равно всегда 1. И это только в том случае, если оно указано статически(в буквальном смысле).

Короче говоря, если это действительно статическое значение, не параметризуйте его.

4 голосов
/ 20 декабря 2011

Если ваш SQL действительно содержит константы (т. Е. Предложение всегда enabled=1), я вижу несколько причин для того, чтобы сделать их литералами в вашем SQL:

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

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

0 голосов
/ 20 декабря 2011

Когда Oracle получает инструкцию SQL, она сначала проверяет, существует ли инструкция SQL и ее план выполнения в кэше. Если это так, это экономит затраты на воссоздание плана выполнения, тем самым экономя время выполнения. Чтобы входящий оператор SQl совпадал с одним в кэше, он должен быть точным (включая летералы, переменные связывания и пробелы). Вот почему рекомендуется использовать переменные связывания, чтобы насыщение оставалось одинаковым для разных значений (и, следовательно, разных литералов) переменной. Но если один и тот же литерал используется постоянно, нет никакой разницы в использовании bind varialbes. В обоих случаях производительность будет одинаковой с точки зрения синтаксического анализа и генерации плана выполнения.

0 голосов
/ 20 декабря 2011

Ответ, как это часто бывает, - «это зависит».

На что? Является ли ваше приложение OLTP (много запросов, небольшие наборы результатов) или DSS (мало запросов, много данных)? Какой перекос в столбцах, на которые вы смотрите, меняется с привязки на литералы? Должны ли эти столбцы быть привязываемыми или всегда привязаны к одним и тем же значениям?

...