Oracle Optimization:哪个执行计划更好?

时间:2016-10-10 12:29:12

标签: oracle plsql query-optimization sql-execution-plan nvl

我要改进此查询:

    SELECT sub.SDDOCO
    FROM( 
      SELECT SDSHAN, SDDOCO, SDMCU, SDLITM, SDIR03, SDVR01
      FROM PRODDTA.F4211 

      UNION ALL

      SELECT SDSHAN, SDDOCO, SDMCU, SDLITM, SDIR03, SDVR01
      FROM PRODDTA.F42119 
    )sub 
    INNER JOIN PRODDTA.F0101 tab 
         ON sub.SDSHAN = tab.ABAN8
    WHERE 
        sub.SDMCU LIKE  CONCAT(CONCAT('%',nvl(:pMCU,SDMCU)),'%') 
    AND sub.SDLITM LIKE  CONCAT(CONCAT('%',nvl(:pLITM,SDLITM)),'%') 
    AND sub.SDIR03 LIKE  CONCAT(CONCAT('%',nvl(:pIR03,SDIR03)),'%')
    AND tab.ABALKY LIKE  CONCAT(CONCAT('%',nvl(:pALKY,ABALKY)),'%')
    AND sub.SDVR01 LIKE  CONCAT(CONCAT('%',nvl(:pVR01,SDVR01)),'%')

我已经以这种方式修改了WHERE条件:

    ((:pMCU IS NOT NULL AND sub.SDMCU LIKE '%' || :pMCU || '%') OR :pMCU IS NULL)
AND ((:pLITM IS NOT NULL AND sub.SDLITM LIKE '%' || :pLITM || '%') OR :pLITM IS NULL)
AND ((:pIR03 IS NOT NULL AND sub.SDIR03 LIKE '%' || :pIR03 || '%') OR :pIR03 IS NULL)
AND ((:pVR01 IS NOT NULL AND sub.SDVR01 LIKE '%' || :pVR01 || '%') OR :pVR01 IS NULL)
AND ((:pALKY IS NOT NULL AND tab.ABALKY LIKE '%' || :pALKY || '%') OR :pALKY IS NULL)

this link,您可以阅读两个查询的执行计划。 哪一个更好? 有什么改进查询的建议吗? 我需要有结果的所有记录

修改: 哪里" F4211" table有71,758条记录,F42119有4,606,154条记录

编辑:和F0101表有634,187条记录。 Whith所有参数都设置为NULL,结果是在不合理的时间(几分钟)内有4,677,925条记录。 没有where子句的查询在58秒内占用4,677,925条记录

修改: 插入代码片段我超过了char的最大数量:( 有关发布执行计划的任何建议吗?

修改: 这是执行计划:

"PLAN_TABLE_OUTPUT"
"Plan hash value: 3925457500"
" "
"-----------------------------------------------------------------------------------------------------------"
"| Id  | Operation                              | Name             | Rows  | Bytes | Cost (%CPU)| Time     |"
"-----------------------------------------------------------------------------------------------------------"
"|   0 | SELECT STATEMENT                       |                  |     2 |  1224 |   614K  (1)| 00:00:24 |"
"|   1 |  NESTED LOOPS                          |                  |     2 |  1224 |   614K  (1)| 00:00:24 |"
"|   2 |   VIEW                                 | index$_join$_004 | 31721 |  1455K| 11379   (1)| 00:00:01 |"
"|*  3 |    HASH JOIN                           |                  |       |       |            |          |"
"|   4 |     INDEX FAST FULL SCAN               | F0101_0          | 31721 |  1455K|  2414   (1)| 00:00:01 |"
"|*  5 |     INDEX FAST FULL SCAN               | F0101_3          | 31721 |  1455K|  8390   (1)| 00:00:01 |"
"|   6 |   VIEW                                 |                  |     1 |   565 |    19   (0)| 00:00:01 |"
"|   7 |    UNION ALL PUSHED PREDICATE          |                  |       |       |            |          |"
"|*  8 |     TABLE ACCESS BY INDEX ROWID BATCHED| F4211            |     1 |   417 |     9   (0)| 00:00:01 |"
"|*  9 |      INDEX RANGE SCAN                  | F4211_4          |     6 |       |     3   (0)| 00:00:01 |"
"|* 10 |     TABLE ACCESS BY INDEX ROWID BATCHED| F42119           |     1 |   422 |    10   (0)| 00:00:01 |"
"|* 11 |      INDEX RANGE SCAN                  | F42119_9         |    10 |       |     3   (0)| 00:00:01 |"
"-----------------------------------------------------------------------------------------------------------"
" "
"Predicate Information (identified by operation id):"
"---------------------------------------------------"
" "
"   3 - access(ROWID=ROWID)"
"   5 - filter(""GGG"".""ABALKY"" LIKE U'%'||NVL(:PALKY,""GGG"".""ABALKY"")||U'%')"
"   8 - filter(""SDMCU"" LIKE U'%'||NVL(:PMCU,""SDMCU"")||U'%' AND ""SDLITM"" LIKE "
"              U'%'||NVL(:PLITM,""SDLITM"")||U'%' AND ""SDIR03"" LIKE U'%'||NVL(:PIR03,""SDIR03"")||U'%' AND ""SDVR01"" "
"              LIKE U'%'||NVL(:PVR01,""SDVR01"")||U'%')"
"   9 - access(""SDSHAN""=""GGG"".""ABAN8"")"
"  10 - filter(""SDMCU"" LIKE U'%'||NVL(:PMCU,""SDMCU"")||U'%' AND ""SDLITM"" LIKE "
"              U'%'||NVL(:PLITM,""SDLITM"")||U'%' AND ""SDIR03"" LIKE U'%'||NVL(:PIR03,""SDIR03"")||U'%' AND ""SDVR01"" "
"              LIKE U'%'||NVL(:PVR01,""SDVR01"")||U'%')"
"  11 - access(""SDSHAN""=""GGG"".""ABAN8"")"

1 个答案:

答案 0 :(得分:1)

1 Oracle具有提高查询性能的良好工具,例如DBMS_SQLTUNE https://docs.oracle.com/database/121/TGSQL/tgsql_sqltune.htm#TGSQL586 在开始时,您可以创建调整任务

declare
  l_task_name varchar2(4000);
begin
 l_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
      sql_text => q'!SELECT sub.SDDOCO
FROM( 
  SELECT SDSHAN, SDDOCO, SDMCU, SDLITM, SDIR03, SDVR01
  FROM PRODDTA.F4211 
  UNION ALL
  SELECT SDSHAN, SDDOCO, SDMCU, SDLITM, SDIR03, SDVR01
  FROM PRODDTA.F42119 
)sub 
INNER JOIN PRODDTA.F0101 tab 
     ON sub.SDSHAN = tab.ABAN8
WHERE 
    sub.SDMCU LIKE  CONCAT(CONCAT('%',nvl(:pMCU,SDMCU)),'%') 
AND sub.SDLITM LIKE  CONCAT(CONCAT('%',nvl(:pLITM,SDLITM)),'%') 
AND sub.SDIR03 LIKE  CONCAT(CONCAT('%',nvl(:pIR03,SDIR03)),'%')
AND tab.ABALKY LIKE  CONCAT(CONCAT('%',nvl(:pALKY,ABALKY)),'%')
AND sub.SDVR01 LIKE  CONCAT(CONCAT('%',nvl(:pVR01,SDVR01)),'%')!'
, bind_list   => sql_binds( anydata.ConvertVarchar2('ABC'), 
            anydata.ConvertVarchar2('BCD'),
            anydata.ConvertVarchar2('CDE'),
            anydata.ConvertVarchar2('DEF'),
            anydata.ConvertVarchar2('EFG'))
, task_name   => 'TEST_TUNING_SQL_SO' 
, description => 'Task to tune a query from StackOverflow');
end;
/

执行后

begin
  DBMS_SQLTUNE.EXECUTE_TUNING_TASK (
   task_name => 'TEST_TUNING_SQL_SO');
end;
/

检索报告并执行建议

select DBMS_SQLTUNE.REPORT_TUNING_TASK(
   task_name => 'TEST_TUNING_SQL_SO') from dual;

2如何公布计划

您可以以文本格式(而非HTML格式)生成它。并尝试仅添加包含谓词信息的计划表。如果不需要,您可以排除任何其他信息。