0

我必须改进这个查询:

    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)

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

编辑:其中“F4211”表有 71,758 条记录,F42119 有 4,606,154 条记录

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

编辑:插入代码片段我超过了最大字符数:(对发布执行计划有什么建议吗?

编辑:这是执行计划:

"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"")"
4

1 回答 1

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)生成它。并尝试仅添加包含谓词信息的计划表。如果不需要,您可以排除任何附加信息。

于 2016-10-12T20:25:11.013 回答