Как заменить определяемую пользователем функцию предложением SELECT?

У меня проблема с производительностью в моем запросе, выполнение которого занимает более 2 минут. В настоящее время основная таблица f_trans содержит 3 миллиона записей.

У меня есть индексированные столбцы в предложении where и условии соединения.

Запрос:

    SELECT f.no AS refno,  
               f.v_date AS v_date,  
               (SELECT fnbalance  
                                     (  
                                      f.acnt_code,  
                                      f.v_date,                                      
                                     )  
                    FROM DUAL) AS balance,  

        FROM   f_trans f JOIN glr_temp glr  
             ON f.acnt_code = glr.acnt_code  
             AND ftr.v_date >= '24-Aug-2014'  
             AND ftr.v_date <= '27-Aug-2014'  
               JOIN glm_gl_mast glm  
               ON f.acnt_code = glm.acnt_code  
             AND glr.acnt_code = glm.acnt_code;  

функция:

    CREATE OR REPLACE function fnbalance (  
p_glcode in   number,p_dtdate in   date,  
)  
   return number  
as  
   openbal   number;  
   dramt     number;  
   cramt     number;  

begin  

   dramt := 0;  
   cramt := 0;  
   balamt := 0;  
                  select nvl (sum (f.dr_amt), 0), nvl (sum (f.cr_amt), 0)  
                    into dramt, cramt  
                    from ftrans ftr  
                   where f.v_source <> 'FFT'    
                     and f.acnt_code = p_glcode  
                     and ftr.ftr_vou_date < p_dtdate;  

   select nvl(( dramt - cramt),0) into balamt from dual;  
   return balamt;  
end  


    Plan hash value: 1037159964

-------------------------------------------------------------------------------------------
| Id  | Operation              | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                  |    53 |  1537 | 23581   (1)| 00:04:43 |
|   1 |  FAST DUAL             |                  |     1 |       |     2   (0)| 00:00:01 |
|*  2 |  HASH JOIN             |                  |    53 |  1537 | 23581   (1)| 00:04:43 |
|*  3 |   HASH JOIN            |                  |  7342 | 73420 |    12   (9)| 00:00:01 |
|   4 |    INDEX FAST FULL SCAN| IND_GLR_ACC      |  5214 | 26070 |     5   (0)| 00:00:01 |
|   5 |    INDEX FAST FULL SCAN| GLM_AC_INDEX     |  7342 | 36710 |     6   (0)| 00:00:01 |
|*  6 |   TABLE ACCESS FULL    | F_TRANS |   181K|  3364K| 23568   (1)| 00:04:43 |
-------------------------------------------------------------------------------------------

Может помочь мне реорганизовать функцию в предложение select?


person saran    schedule 08.10.2014    source источник
comment
Сделайте следующее, EXPLAIN PLAN FOR <URQUERY>, а затем SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY).. Вставьте вывод сюда..   -  person Maheswaran Ravisankar    schedule 08.10.2014


Ответы (1)


И ftr.v_date >= '24 августа 2014'
И ftr.v_date ‹= '27 августа 2014'

Во-первых, такой способ сравнения даты с литералом очень плох. v_date является типом данных DATE, вы должны сравнивать его с датами, а не с литералами. Используйте TO_DATE для преобразования литерала в дату.

AND ftr.v_date >= TO_DATE('24-Aug-2014', 'DD-Mon-YYYY')
AND ftr.v_date <= TO_DATE('27-Aug-2014', 'DD-Mon-YYYY')

Скажите себе: никогда не полагайтесь на неявные преобразования данных. Всегда делайте это явно.

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

Обновить

Узнайте, как сгенерировать план выполнения в SQL*Plus.

SQL> explain plan for select * from dual;

Explained.

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 272002086

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     2 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

8 rows selected.

SQL>

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

person Lalit Kumar B    schedule 08.10.2014
comment
Спасибо лалит. Я изменил, но проблема все еще сохраняется. - person saran; 08.10.2014
comment
Опубликуйте план выполнения по запросу. - person Lalit Kumar B; 08.10.2014
comment
я не мог добавить свой план как изображение :( - person saran; 08.10.2014
comment
изображение не требуется. Смотрите мое обновление в ответе, чтобы узнать, как опубликовать план выполнения. - person Lalit Kumar B; 08.10.2014
comment
я выложил план выполнения - person saran; 08.10.2014
comment
Это не является полным, включите информацию предиката. Вставьте весь вывод dbms_xplan.display - person Lalit Kumar B; 08.10.2014
comment
Хорошо видно, что стол f_trans идет на жеребьевку из-за full table scan. Индексирован ли столбец acnt_code? - person Lalit Kumar B; 08.10.2014