2016-10-04 1 views
0

Ich wundere mich über das folgende seltsame Verhalten.Transaktionsverhalten mit Subselect

Diese Funktion sollte die ausgewählten Daten in eine Tabelle ps_cs_corr_data_tb (diese Tabelle ist leer) log:

create or replace function cs_corr_data(i_id in varchar2, 
             i_key1 in varchar2, 
             i_key2 in varchar2, 
             i_key3 in varchar2, 
             i_key4 in varchar2, 
             i_key5 in varchar2) 
    return number as pragma autonomous_transaction; 
begin 

    insert into ps_cs_corr_data_tb 
    (descr, 
    cs_key_id_01, 
    cs_key_id_02, 
    cs_key_id_03, 
    cs_key_id_04, 
    cs_key_id_05) 
    values 
    (i_id, i_key1, i_key2, i_key3, i_key4, i_key5); 
    commit; 
    return 1; /* insert successful */ 
exception 
    when dup_val_on_index then 
    return 0; 
end; 

Test a)

Der Test mit der folgenden select-Anweisung erfolgreich war (wie erwartet):

select b.id, b.key1, b.key2, b.key3, b.key4, b.key5 
    from (select a.id, a.key1, a.key2, a.key3, a.key4, a.key5 
      from (-- test data 
       select '1' as id,'1' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all 
       select '1' as id,'2' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all 
       select '1' as id,'3' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all 
       select '1' as id,'4' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all 
       select '1' as id,'5' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual 
       ) a 
     -- some conditions   
     where a.id = '1' 
      and a.key1 = '4') b 
-- log the results of selection   
where cs_corr_data(b.id, b.key1, b.key2, b.key3, b.key4, b.key5) = 1; 

Ergebnis der Auswahl:

ID KEY1 KEY2 KEY3 KEY4 KEY5 
1 4     

Ergebnis in Logging-Tabelle:

select * from ps_cs_corr_data_tb d; 

DESCR CS_KEY_ID_01 CS_KEY_ID_02 CS_KEY_ID_03 CS_KEY_ID_04 CS_KEY_ID_05 
1  4     

Bisher das erwartete Ergebnis!

-Plan erklären:

Plan hash value: 334628103 

------------------------------------------------------------------------- 
| Id | Operation  | Name | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  5 | 90 |  2 (0)| 00:00:01 | 
| 1 | VIEW   |  |  5 | 90 |  2 (0)| 00:00:01 | 
| 2 | UNION-ALL  |  |  |  |   |   | 
|* 3 | FILTER  |  |  |  |   |   | 
| 4 |  FAST DUAL |  |  1 |  |  2 (0)| 00:00:01 | 
|* 5 | FILTER  |  |  |  |   |   | 
| 6 |  FAST DUAL |  |  1 |  |  2 (0)| 00:00:01 | 
|* 7 | FILTER  |  |  |  |   |   | 
| 8 |  FAST DUAL |  |  1 |  |  2 (0)| 00:00:01 | 
|* 9 | FILTER  |  |  |  |   |   | 
| 10 |  FAST DUAL |  |  1 |  |  2 (0)| 00:00:01 | 
|* 11 | FILTER  |  |  |  |   |   | 
| 12 |  FAST DUAL |  |  1 |  |  2 (0)| 00:00:01 | 
------------------------------------------------------------------------- 

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

    3 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','1',' ',' ',' ',' 
       ')=1) 
    5 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','2',' ',' ',' ',' 
       ')=1) 
    7 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','3',' ',' ',' ',' 
       ')=1) 
    9 - filter("CS_CORR_DATA"('1','4',' ',' ',' ',' ')=1) 
    11 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','5',' ',' ',' ',' 
       ')=1) 

Test b)

Jetzt der gleiche Test mit unterschiedlichen Testdatenaufbereitung (aber den gleichen Testdaten):

select b.id, b.key1, b.key2, b.key3, b.key4, b.key5 
    from (select a.id, a.key1, a.key2, a.key3, a.key4, a.key5 
      from (select '1' as id, 
         to_char(level) as key1, 
         ' ' as key2, 
         ' ' as key3, 
         ' ' as key4, 
         ' ' as key5 
        from dual 
       connect by level <= 5) a 
     where a.id = '1' 
      and a.key1 = '4') b 
where cs_corr_data(b.id, b.key1, b.key2, b.key3, b.key4, b.key5) = 1; 

Ergebnis der Auswahl:

ID KEY1 KEY2 KEY3 KEY4 KEY5 
1 4     

Ergebnis in Logging-Tabelle:

select * from ps_cs_corr_data_tb d; 

DESCR CS_KEY_ID_01 CS_KEY_ID_02 CS_KEY_ID_03 CS_KEY_ID_04 CS_KEY_ID_05 
1  1     
1  2     
1  3     
1  4     
1  5     

Erklären-Plan:

Plan hash value: 2403765415 

-------------------------------------------------------------------------------------- 
| Id | Operation      | Name | Rows | Bytes | Cost (%CPU)| Time  | 
-------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |  |  1 | 37 |  2 (0)| 00:00:01 | 
|* 1 | VIEW       |  |  1 | 37 |  2 (0)| 00:00:01 | 
|* 2 | CONNECT BY WITHOUT FILTERING|  |  |  |   |   | 
| 3 | FAST DUAL     |  |  1 |  |  2 (0)| 00:00:01 | 
-------------------------------------------------------------------------------------- 

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

    1 - filter("CS_CORR_DATA"("A"."ID","A"."KEY1","A"."KEY2","A"."KEY3","A"."KE 
       Y4","A"."KEY5")=1 AND "A"."ID"='1' AND "A"."KEY1"='4') 
    2 - filter(LEVEL<=5) 

Irgendwelche Ideen, was hier vor sich geht?

+0

Scheint wie die zweite Abfrage hat das äußere Prädikat in die a-Unterabfrage gedrückt. Bitte erstellen Sie die Ausführungspläne für beide Abfragen und aktualisieren Sie Ihre Frage, um sie aufzunehmen. – Boneist

+0

@Boneix Ausführungspläne hinzugefügt. Vielen Dank für Ihre Hilfe –

Antwort

2

Oracle (zusammen mit fast jeder relationalen Datenbank) ist frei, Prädikate in der Reihenfolge zu bewerten, in der es am effizientesten ist. In jeder Abfrage kann das Funktionsprädikat zuerst ausgewertet oder die a.id = '1' and a.key1 = '4' Prädikate zuerst ausgewertet oder das Funktionsprädikat zwischen diesen beiden Prädikaten ausgewertet werden. Es scheint, dass der tatsächliche Plan, den der Optimierer im zweiten Fall (zumindest dieses Mal) auswählte, darin bestand, die Funktion zuerst auszuwerten, während er entschied, die Funktion im ersten Fall zu bewerten. Natürlich kann der Optimierer in beiden Fällen morgen seine Meinung ändern, sodass Sie nicht auf einen bestimmten Abfrageplan angewiesen sind.

+0

Danke, d. H. Oracle arbitrary arrangiert die Bedingungen der inneren und äußeren Select-Anweisungen (siehe Ausführungspläne). Ich habe das nicht berücksichtigt. –