2016-10-10 11 views
0

私はこのクエリを改善するためにきました:this linkOracleの最適化:どの実行計画が優れていますか?

((: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) 

あなたは、両方のクエリの実行プランを読むことができます:

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条件を変更しました。 どちらが良いですか? クエリを改善するためのご提案がありますか? F0101テーブル634187件のレコードを持っている:「F4211」の表では、71758本の記録を持っており、F42119はEDITは4606154のレコードの

を持って : は、私は結果

EDITのすべてのレコードを持っている必要があります。 WhithすべてのパラメータがNULLに設定された場合、結果は不当な時間(数分)で4,677,925レコードになります。 挿入コードsnippents Iがcharの最大num個を超え:( 実行計画を投稿するために、任意の提案

EDIT:? この は、where句のないクエリが58秒

EDITで4677925件のレコードを取ります

"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

(1)おそらく簡単にこのクエリを改善することはできません。 (2)すべてのカラム名を修飾して、どこから来たのかを知る必要があります。 –

+0

@ GordonLinoff thx、私は列を修飾しました –

+1

テーブルを持つ行の数はいくつですか?すべての行が一瞬で(すべての行/最初の行)必要ですか? –

答えて

1

1 Oracleには、問合せのパフォーマンスを改善するための機能があります(例:DBMS_SQLTUNE)。あなたは

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

それを実行し、レポートを取得し、計画

をpublicateする方法

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

2のアドバイスを行うことができるした後は、チューニング・タスク

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; 
/

を作成することができ始める時

テキスト形式で生成することができます(iではなくn HTML)。そして、述語に関する情報を持つ計画表のみを追加しようとします。追加情報が不要な場合は除外することができます。

+0

(1) - スクロールしましたが、このエラーが発生しました。ORA-13616:現在のユーザーにADVISOR権限が付与されていません。 (2) - SqlDeveloperはテキストでプランを生成しません。 –

+1

(2)SQLPLUS 'EXPLAIN PLAN FOR PLUSのデュアル;と' SELECT * FROM table(DBMS_XPLAN.DISPLAY);の後の単純な例SQLの開発者でも機能すると思います –

+0

クエリテーブルのgather_table_statsを使用できますか?たとえば、 'begin DBMS_STATS.GATHER_TABLE_STATS( 'PRODDTA'、 'F4211');終わり。そして、プランの変更はありますか? –

関連する問題