2017-06-08 1 views
0

Ich muss die Ausführungszeit davon verringern. Diese Anweisung Verarbeitung verschwenden etwa 30 Minuten, wenn ich gerade auf ": i_member_name" eingefügt, alle anderen ist null.Wie wählt man optionale Parameter auf Orakel (Ausführungszeit von Orakel verringern)?

Wenn ich so ausführen, ist es in Ordnung, nur 30 Sekunden verschwendet.

SELECT 

    A.MEMBER_NUM, A.MEMBER_NAME, B.MEMBER_INFO FROM REG_MEMBER A, MEMBER_DETAIL B 

    WHERE A.MEMBER_ID = B.MEMBER_ID 

    AND (LOWER(A.MEMBER_NAME) LIKE LOWER(:i_member_name || '%'))  

    --AND (LOWER(B.MEMBER_INFO) LIKE LOWER(:i_member_info || '%')) 

    --AND (A.MEMBER_NUM LIKE :i_member_num || '%') 

    --AND (LOWER(B.MEMBER_ADD) LIKE LOWER('%' || :i_member_add || '%')) 

Also habe ich eine Frage: Wie Parameter zu überprüfen ist Null, dann nicht gegen mehr Ausführungszeit lesen. so etwas wie dieser

  SELECT A.MEMBER_NUM, A.MEMBER_NAME, B.MEMBER_INFO FROM REG_MEMBER A, MEMBER_DETAIL B   
        WHERE 
(LOWER(A.MEMBER_NAME) LIKE LOWER(:i_member_name || '%'))  
     and case when :i_member_num is null then return 
     else (A.MEMBER_NUM LIKE :i_member_num || '%') 
    end 
+0

Verwenden Sie boolesche Logik. Ändere 'AND (LOWER (B.MEMBER_INFO) WIE LOWER (: i_member_info || '%'))' to '(UND (LOWER (B.MEMBER_INFO) WIE LOWER (: i_member_info || '%')) ODER: i_member_info IST NULL) '. Dies kann jedoch keinen Unterschied machen - Sie müssen den Abfrageplan verwenden, um zu überprüfen, –

+0

Vielleicht gibt es einen anderen Weg - erstellen Sie einen Index auf 'low (member_name)' etc.? Da Sie innerhalb von 'lower()' springen müssen, hilft ein Index für 'member_name' nicht. – mathguy

+0

Können Sie mir mehr angeben? – Solution

Antwort

0

Der schnellste Weg für optionale Parameter zu überprüfen, in SQL in der Regel mit NVL ist.

Oracle kann oft einen NVL Ausdruck in zwei separate Teilpläne erweitern. Eine Operation FILTER funktioniert zur Laufzeit, um nur einen Teil des Plans auszuwählen. Zum Beispiel kann ein INDEX RANGE SCAN mit einem Bind-Wert wie 'Smith%' verwendet werden, der sargable ist; und es kann einen TABLE ACCESS FULL mit einem Bind-Wert wie NULL verwenden, der nicht sargable ist.

Unten ist ein Beispiel eine kleine Teilmenge der Objekte in Ihrer Frage mit:

--Create table and index. 
create table reg_member(member_num number, member_name varchar2(100)); 
create index reg_member_idx on reg_member(lower(member_name)); 

--Generate explain plan. 
EXPLAIN PLAN FOR 
SELECT 
    A.MEMBER_NUM, A.MEMBER_NAME 
FROM REG_MEMBER A 
WHERE NVL(:i_member_name, LOWER(A.MEMBER_NAME)) = LOWER(A.MEMBER_NAME); 

--Show explain plan. 
select * from table(dbms_xplan.display); 

Plan hash value: 3501926772 

---------------------------------------------------------------------------------------------------------- 
| Id | Operation        | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT      |     |  2 | 130 |  3 (0)| 00:00:01 | 
| 1 | VIEW         | VW_ORE_377C5901 |  2 | 130 |  3 (0)| 00:00:01 | 
| 2 | UNION-ALL       |     |  |  |   |   | 
|* 3 | FILTER        |     |  |  |   |   | 
| 4 |  TABLE ACCESS BY INDEX ROWID BATCHED| REG_MEMBER  |  1 | 117 |  1 (0)| 00:00:01 | 
|* 5 |  INDEX RANGE SCAN     | REG_MEMBER_IDX |  1 |  |  1 (0)| 00:00:01 | 
|* 6 | FILTER        |     |  |  |   |   | 
|* 7 |  TABLE ACCESS FULL     | REG_MEMBER  |  1 | 117 |  2 (0)| 00:00:01 | 
---------------------------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    3 - filter(:I_MEMBER_NAME IS NOT NULL) 
    5 - access(LOWER("MEMBER_NAME")=:I_MEMBER_NAME) 
    6 - filter(:I_MEMBER_NAME IS NULL) 
    7 - filter(LOWER("MEMBER_NAME") IS NOT NULL) 

Note 
----- 
    - dynamic statistics used: dynamic sampling (level=2) 

NVLFILTER Operationen können in einigen Fällen große Arbeit. Aber es ist schwer zu sagen, ob es Ihr spezifisches Problem beheben würde, weil es so viele Variablen gibt: Haben die Objekte die richtigen Indizes, wie arbeiten alle Prädikate zusammen usw. Aber NVL ist ein guter Anfang.

+0

Muss ich EXPLAIN-Plan für alle anderen Parameter generieren? /: i_member_info,: i_member_add,: i_member_num/ Muss ich für jeden einen Index erstellen? – Solution

+1

@ user2801618 Sie müssen nur 'EXPLAIN PLAN' verwenden, um den Plan zu überprüfen. Da Ihre Abfrage möglicherweise eine beliebige Kombination der Spalten verwenden könnte, wäre es meines Erachtens sinnvoll, alle relevanten Spalten und Ausdrücke zu indizieren. –

+0

'create index reg_member_idx auf reg_member (lower (member_name)); Index reg_member_idx2 auf reg_member erstellen (niedriger (i_member_num)); Index reg_member_idx3 auf reg_member erstellen (niedriger (i_member_add)); ' So was? – Solution