Может ли использование VIEW для операций SELECT повысить производительность? - PullRequest
3 голосов
/ 26 февраля 2009

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

Итак, мне интересно, компилирует ли oracle Plan план выполнения для своих представлений?

Предположим, что у меня есть определенный запрос, который используется 10000 раз во время запроса. Запрос выглядит примерно так:

select A, B, C 
from aTbl, bTbl left join cTbl on bTbl.cTblID = cTbl.objectkey
where aTbl.objectkey = bTbl.parentkey

В коде я хотел бы получить результат запроса выше с дополнительным параметром фильтрации, например: WHERE aTbl.flag1 = <<NUMBER>>

Теперь у меня есть 2 варианта:

  1. Создание подготовленного оператора с использованием приведенного выше SQL, затем повторное использование объекта.
  2. Помещение вышеуказанного select (aTbl, bTbl, cTbl) в VIEW, затем создание подготовленного оператора для этого представления, что дает преимущество от предварительно скомпилированного плана выполнения b Oracle.

Что бы вы предложили?

Ответы [ 6 ]

6 голосов
/ 26 февраля 2009

Oracle может выдвинуть предикат в представление, если думает, что это улучшит план.

Если вы хотите избежать этого, вы можете использовать одно из следующих:

  1. Добавить /*+ NO_MERGE */ или /*+ NO_PUSH_PRED */ подсказку в определение вида
  2. Добавьте подсказку /*+ NO_MERGE (view) */ или /*+ NO_PUSH_PRED (view) */ в запрос, который использует представление.

Если вы хотите форсировать это, используйте их couterparts /*+ PUSH_PRED */ и /*+ MERGE */

Что касается производительности, то нет никакой разницы между использованием определенного представления (если это, конечно, не MATERIALIZED VIEW) или встроенным представлением (т.е. подзапросом).

Oracle компилирует планы не для видов, а для точных SQL текстов.

То есть для следующих утверждений:

SELECT A, B, C 
FROM   aTbl, bTbl
LEFT JOIN cTbl ON 
  bTbl.cTblID = cTbl.objectkey
WHERE aTbl.objectkey = bTbl.parentkey
  AND aTbl.flag1 = :NUMBER

SELECT *
FROM
  (
  SELECT A, B, C, flag1
  FROM   aTbl, bTbl
  LEFT JOIN cTbl ON 
    bTbl.cTblID = cTbl.objectkey
  WHERE aTbl.objectkey = bTbl.parentkey
  )
WHERE flag1 = :NUMBER

/*
CREATE VIEW v_abc AS
SELECT A, B, C, flag1 
FROM   aTbl, bTbl
LEFT JOIN cTbl ON 
  bTbl.cTblID = cTbl.objectkey
WHERE aTbl.objectkey = bTbl.parentkey
*/

SELECT A, B, C
FROM v_abc
WHERE flag1 = :NUMBER

план будет:

  1. Будьте такими же (если Oracle выберет предикат, что более чем вероятно);
    • Быть скомпилированным при первом вызове;
    • Повторно использовать при повторном вызове.
2 голосов
/ 26 февраля 2009

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

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

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

2 голосов
/ 26 февраля 2009

Вид здесь не совсем то, что вам нужно.

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

Так же, как стилистическая заметка - вы должны решить, как вы указываете объединения, и согласиться с этим, для согласованности и удобочитаемости. Таким образом, у вас есть явное условие соединения для atbl и btbl, а синтаксис "left join" для btbl и ctbl .. на самом деле не имеет значения в схеме вещей, но выглядит и читает немного странно.

Удачи!

1 голос
/ 27 февраля 2009

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

Вот документы Oracle по использованию материализованных представлений.

0 голосов
/ 26 февраля 2009

ответ здесь ДА и НЕТ.

oracle будет анализировать только один оператор один раз. ключ в том, что он должен быть «идентичным», а не просто похожим. это включает интервалы (или вкладки) и комментарии.

создание представления с помощью create view позволяет исправить оператор как есть и разрешить его повторное использование.

однако.

SELECT * FROM VIEW
и
SELECT * FROM VIEW WHERE A=1

- это 2 разных оператора / запроса.

чтобы получить максимальный коэффициент повторного использования, вы ДОЛЖНЫ ИСПОЛЬЗОВАТЬ переменные связывания, а не просто объединять условия в SELECT. и что обычно означает подготовленные отчеты

Вы не упомянули, какой язык хоста, если так, скажем, я обновлю с конкретным примером, если смогу.

в PL / SQL

DECLARE
  cursor c (cpflag aTbl.flag1%TYPE )is
   select A, B, C 
     from aTbl, bTbl, cTbl
    where aTbl.objectkey = bTbl.parentkey
      and bTbl.cTblID = cTbl.objectkey
      and aTbl.flag1 = cp_flag ;

vtype c%rowtype;
BEGIN

open c(100);
fetch c into vtype;
close c;

open c(200);
fetch c into vtype;
close c;
END;

в таких вещах, как java готовит записи, которые вы ставите "?" в качестве плашдолеров и использовать вызовы stmt.bind ()

надеюсь, что это поможет

0 голосов
/ 26 февраля 2009

В Oracle нет «предварительной компиляции» представлений: выбор из определенного представления не отличается по производительности от выбора непосредственно из таблицы (при условии, что все объединения и условия одинаковы).

Я озадачен, когда вы говорите, что ваш запрос "используется 10000 раз во время запроса". Это не звучит оптимально - почему это так?

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