2012-06-20 3 views
0

В одном из моих проектов я запускаю прямой запрос в режиме просмотра с использованием dblink, но после проверки производительности наблюдается, что это дорого (много использования Nested Looping, High CPU).Лучший способ оптимизации запросов Oracle

Теперь мы нашли одно решение i.e. Используйте функцию для запуска этих запросов на просмотр. Так это правильное решение или есть лучший способ выполнить эту операцию.

Пример запроса и есть отчет об исполнении:

  1. без использования функции:

Запрос:

SELECT t1., 
     t2. 
FROM table1 t1 
     join table2 t2 
     ON t1.id = t2.id 
WHERE t1.bookingId = '0250014547' 

Отчет:

SQL> explain plan for SELECT t1., t2. FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id WHERE t1.bookingId = '0250014547'; 

SQL> select * from table(dbms_xplan.display); 

------------------------------------------------------------------------------------------- 
| Id | Operation      | Name      | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT     |       |  1 | 331 |  6 (0)| 00:00:01 | 
| 1 | NESTED LOOPS     |       |  1 | 331 |  6 (0)| 00:00:01 | 
| 2 | NESTED LOOPS     |       |  1 | 299 |  5 (0)| 00:00:01 | 
| 3 | NESTED LOOPS     |       |  1 | 210 |  4 (0)| 00:00:01 | 
| 4 |  NESTED LOOPS     |       |  1 | 185 |  3 (0)| 00:00:01 | 
| 5 |  NESTED LOOPS    |       |  1 | 156 |  2 (0)| 00:00:01 | 
|* 6 |  TABLE ACCESS BY INDEX ROWID| GENERAL_ACCT_MAST_TABLE |  1 | 66 |  1 (0)| 00:00:01 | 
|* 7 |  INDEX UNIQUE SCAN   | IDX_GAM_FORACID   |  1 |  |  1 (0)| 00:00:01 | 
| 8 |  TABLE ACCESS BY INDEX ROWID| SERVICE_OUTLET_TABLE  | 1694 | 148K|  1 (0)| 00:00:01 | 
|* 9 |  INDEX UNIQUE SCAN   | IDX_SERVICE_OUTLET_TABLE |  1 |  |  1 (0)| 00:00:01 | 
| 10 |  TABLE ACCESS BY INDEX ROWID | GEN_SCHM_PARM_TABLE  | 356 | 10324 |  1 (0)| 00:00:01 | 
|* 11 |  INDEX UNIQUE SCAN   | IDX_GEN_SCHM_PARM_TABLE |  1 |  |  1 (0)| 00:00:01 | 
|* 12 |  TABLE ACCESS BY INDEX ROWID | ACCT_STATEMENT_TABLE  | 12M| 309M|  1 (0)| 00:00:01 | 
|* 13 |  INDEX UNIQUE SCAN   | IDX_ACCT_STATEMENT_TABLE |  1 |  |  1 (0)| 00:00:01 | 
| 14 | TABLE ACCESS BY INDEX ROWID | CUST_MAST_GEN_TABLE  | 24M| 2119M|  1 (0)| 00:00:01 | 
|* 15 |  INDEX UNIQUE SCAN   | IDX_CUST_MAST_GEN_TABLE |  1 |  |  1 (0)| 00:00:01 | 
| 16 | TABLE ACCESS BY INDEX ROWID | BRANCH_BIC_TABLE   | 65258 | 2039K|  1 (0)| 00:00:01 | 
|* 17 | INDEX UNIQUE SCAN    | IDX_BRANCH_BIC_TABLE  |  1 |  |  1 (0)| 00:00:01 | 
------------------------------------------------------------------------------------------- 
  1. Использование функции:

Запрос:

SELECT Funquery1('0250014547') 
FROM dual; 

Отчет:

SQL> explain plan for select gtt('0252050014577') from dual; 

SQL> select * from table(dbms_xplan.display); 

----------------------------------------------------------------- 
| Id | Operation  | Name | Rows | Cost (%CPU)| Time  | 
----------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  2 (0)| 00:00:01 | 
| 1 | FAST DUAL  |  |  1 |  2 (0)| 00:00:01 | 
----------------------------------------------------------------- 
+0

и что делает 'Funquery1'? – Sathya

+0

имеет тот же запрос, о котором я упомянул выше, который возвращает результат в курсоре. – Sham

ответ

2

ли второй запрос реально работать быстрее?

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

Насколько точны статистические данные по таблицам? Являются ли оценки мощности в плане запроса разумно близкими к реальности? Насколько избирательным является предикат t1.bookingId = '0250014547'? Подходит ли bookingID первичным ключом t1?

Текст вашего вопроса касается ссылки на базу данных, но ни запрос, который вы отправили, ни план запроса, похоже, не ссылаются на объект в удаленной базе данных. Текст вашего вопроса говорит о представлении, но указанный вами запрос не относится к каким-либо представлениям. Запрос, который вы опубликовали, объединяет две таблицы, план запроса объединяется. 7. Эти несоответствия обычно усложняют предложение любых предложений.

+0

(Justin) Спасибо за информацию .. Поскольку прямо сейчас мы используем сервер UAT, а не сервер Production, поэтому вы не найдете ни одного dblink, просмотра в этом запросе, но в действительности запрос запускается при просмотре с использованием dblink. Здесь bookingID - ПЕРВЫЙ КЛЮЧ. – Sham

0

Justin (+1) точно соответствует действительности. ПЛАН EXPLAIN показывает вам вызов функции и не показывает вам ничего, что происходит внутри функции.

В SQLPlus используйте

set autotrace on 

Это даст вам фактическую статистику выполнения инструкции, включая любой рекурсивный SQL, который не показан на EXPLAIN PLAN выходе.

Для более совершенной настройки вы можете использовать событие трассировки Oracle 10046. Но SQLPlus «autotrace» может быть достаточным для ваших целей.

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

Смежные вопросы