2012-04-13 7 views
1

Ich habe eine SELECT-Anweisung in ORACLE:Wie kann ich die SELECT-Anweisung optimieren, die auf einer Oracle-Datenbank ausgeführt wird?

SELECT COUNT(DISTINCT ds1.endpoint_msisdn)     multiple30, 
     dss1.service, 
     dss1.endpoint_provisioning_id, 
     dss1.company_scope, 
     Nvl(x.subscription_status, dss1.subscription_status) subscription_status 
FROM daily_summary ds1 
     join daily_summary ds2 
     ON ds1.endpoint_msisdn = ds2.endpoint_msisdn, 
     daily_summary_static dss1, 
     daily_summary_static dss2, 
     (SELECT NULL subscription_status 
     FROM dual 
     UNION ALL 
     SELECT -2 subscription_status 
     FROM dual) x 
WHERE ds1.summary_ts >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
     AND ds1.summary_ts <= To_date('10-04-2012', 'dd-mm-yyyy') 
     AND dss1.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
     AND dss1.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 
     AND dss2.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
     AND dss2.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 
     AND dss1.service <> dss2.service 
     AND (dss1.company_scope = 2 
       OR dss1.company_scope = 5) 
     AND (dss2.company_scope = 2 
       OR dss2.company_scope = 5) 
     AND dss1.company_scope = dss2.company_scope 
     AND ds1.endpoint_noc_id = dss1.endpoint_noc_id 
     AND ds1.endpoint_host_id = dss1.endpoint_host_id 
     AND ds1.endpoint_instance_id = dss1.endpoint_instance_id 
     AND ds2.endpoint_noc_id = dss2.endpoint_noc_id 
     AND ds2.endpoint_host_id = dss2.endpoint_host_id 
     AND ds2.endpoint_instance_id = dss2.endpoint_instance_id 
     AND dss1.endpoint_provisioning_id = dss2.endpoint_provisioning_id 
     AND Least(1, ds1.total_actions) = 1 
     AND Least(1, ds2.total_actions) = 1 
GROUP BY dss1.service, 
      dss1.endpoint_provisioning_id, 
      dss1.company_scope, 
      Nvl(x.subscription_status, dss1.subscription_status); 

Diese Abfrage etwa 26 Minuten in Anspruch nahm in meiner Umgebung zurückzukehren, aber wenn ich den Abschnitt zu entfernen:

dss1.last_active >= to_date('10-04-2012','dd-mm-yyyy') - 30 AND 
        dss1.last_active <= to_date('10-04-2012','dd-mm-yyyy') AND 
        dss2.last_active >= to_date('10-04-2012','dd-mm-yyyy') - 30 AND 
        dss2.last_active <= to_date('10-04-2012','dd-mm-yyyy') AND 

es dauerte nur 20 Sekunden laufen .

Wir haben Index auf die Spalte last_active, ich weiß nicht, warum der Abschnitt die Leistung so sehr verlangsamen? irgendwelche Ideen?


Wenn ich das ausführen, war es sehr schnell.

select * from daily_summary_static where last_active >= to_date('10-04-2012','dd-mm-yyyy') - 30 AND last_active <= to_date('10-04-2012','dd-mm-yyyy');


Erklären Plan für die Anweisung, ich habe keine vollständige Tabelle finden Sie hier scannen, weiß nicht, warum es so langsam laufen:

---------------------------------------------------------------------------------------------------------------- 
| Id | Operation        | Name     | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT      |      |  1 | 119 | 204 (3)| 00:00:03 | 
| 1 | SORT GROUP BY       |      |  1 | 119 | 204 (3)| 00:00:03 | 
| 2 | MERGE JOIN CARTESIAN     |      |  1 | 119 | 203 (2)| 00:00:03 | 
|* 3 | TABLE ACCESS BY INDEX ROWID   | DAILY_SUMMARY  |  1 | 27 | 11 (0)| 00:00:01 | 
| 4 |  NESTED LOOPS      |      |  1 | 116 | 199 (3)| 00:00:03 | 
|* 5 |  HASH JOIN       |      |  3 | 267 | 178 (3)| 00:00:03 | 
|* 6 |  HASH JOIN       |      |  1 | 65 | 140 (2)| 00:00:02 | 
| 7 |  TABLE ACCESS BY INDEX ROWID  | DAILY_SUMMARY_STATIC | 61 | 1647 | 37 (3)| 00:00:01 | 
| 8 |   BITMAP CONVERSION TO ROWIDS  |      |  |  |   |   | 
| 9 |   BITMAP AND      |      |  |  |   |   | 
| 10 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
| 11 |   SORT ORDER BY    |      |  |  |   |   | 
|* 12 |    INDEX RANGE SCAN   | DSS_LAST_ACTIVE  | 560 |  |  3 (0)| 00:00:01 | 
| 13 |   BITMAP OR      |      |  |  |   |   | 
| 14 |   BITMAP CONVERSION FROM ROWIDS|      |  |  |   |   | 
|* 15 |    INDEX RANGE SCAN   | DSS_C_SCOPE_IDX  | 560 |  | 18 (0)| 00:00:01 | 
| 16 |   BITMAP CONVERSION FROM ROWIDS|      |  |  |   |   | 
|* 17 |    INDEX RANGE SCAN   | DSS_C_SCOPE_IDX  | 560 |  |  1 (0)| 00:00:01 | 
| 18 |  TABLE ACCESS BY INDEX ROWID  | DAILY_SUMMARY  | 1773 | 67374 | 102 (0)| 00:00:02 | 
|* 19 |   INDEX RANGE SCAN    | DS_DAILY_ACTIVE_IDX | 1767 |  | 14 (0)| 00:00:01 | 
| 20 |  TABLE ACCESS BY INDEX ROWID  | DAILY_SUMMARY_STATIC | 61 | 1464 | 37 (3)| 00:00:01 | 
| 21 |  BITMAP CONVERSION TO ROWIDS  |      |  |  |   |   | 
| 22 |   BITMAP AND      |      |  |  |   |   | 
| 23 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
| 24 |   SORT ORDER BY     |      |  |  |   |   | 
|* 25 |   INDEX RANGE SCAN    | DSS_LAST_ACTIVE  | 560 |  |  3 (0)| 00:00:01 | 
| 26 |   BITMAP OR      |      |  |  |   |   | 
| 27 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
|* 28 |   INDEX RANGE SCAN    | DSS_C_SCOPE_IDX  | 560 |  | 18 (0)| 00:00:01 | 
| 29 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
|* 30 |   INDEX RANGE SCAN    | DSS_C_SCOPE_IDX  | 560 |  |  1 (0)| 00:00:01 | 
|* 31 |  INDEX RANGE SCAN     | DS_PKEY    |  8 |  |  2 (0)| 00:00:01 | 
| 32 | BUFFER SORT       |      |  2 |  6 | 193 (3)| 00:00:03 | 
| 33 |  VIEW        |      |  2 |  6 |  4 (0)| 00:00:01 | 
| 34 |  UNION-ALL       |      |  |  |   |   | 
| 35 |  FAST DUAL       |      |  1 |  |  2 (0)| 00:00:01 | 
| 36 |  FAST DUAL       |      |  1 |  |  2 (0)| 00:00:01 | 
---------------------------------------------------------------------------------------------------------------- 
+0

Es ist immer noch sehr lange dauern, wenn ich das entfernen ** - 30 ** Bedingung. was verwirrt mich ist, warum die datum manipulation auf dss war so langsam, aber es war schnell, wenn bei der datum manipulation auf ds.? da die datensätze in ds weit mehr waren als dss ... und wir haben index auf last_active in dss. –

+0

In diesen Zeilen gibt es keine intensive Datumsmanipulation, da die Werte, mit denen Sie 'last_active' vergleichen, statisch sind und nur einmal berechnet werden. Sie sagen, Sie haben einen Index, aber sind Sie sicher, dass der Optimizer ihn verwendet? Können Sie die Ausführungspläne für beide Fälle hinzufügen? –

+0

Hallo Erkan, der EXPLAIN-Plan wurde im ursprünglichen Beitrag hinzugefügt, diese Erklärung ist für die "langsame" SELECT-Anweisung, ich sehe hier keinen vollständigen Tabellenscan, der Indexbereich-Scan ist auf dem Index passiert ** DSS_LAST_ACTIVE **, don Warum läuft es so langsam? –

Antwort

2

Da dieser Abschnitt tatsächlich macht es langsamer:

AND dss1.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND dss1.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 
AND dss2.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND dss2.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 

es mir, dass der Index aufwahrscheinlich scheint 0 wird verwendet, wenn dies nicht der Fall ist, d. H. Es verhindert die Verwendung eines anderen, nützlicheren Index. Meine Wette ist auf einem anderen Index, der für das Verbinden von dss1 und dss2 verwendet werden würde, aber tatsächlich ist es nicht wirklich wichtig.

Daher schlage ich vor Indexnutzung zu deaktivieren, indem er bewusst nicht mehr den Block wie diese so den Abfrageoptimierer Änderung des Index verwenden:

AND (dss1.last_active+0) >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND (dss1.last_active+0) <= To_date('10-04-2012', 'dd-mm-yyyy') 
AND (dss2.last_active+0) >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND (dss2.last_active+0) <= To_date('10-04-2012', 'dd-mm-yyyy') 
+1

Ich denke auch, dass die Verwendung von Index die Ursache sein könnte, könnten wir auch NO_INDEX Hinweis verwenden, um dies zu erreichen. –

+0

Danke ammoQ. das hilft wirklich. Ich habe den Sql geändert, wie Sie es vorgeschlagen haben, es funktioniert! es endete in 20 Sekunden. Eine Frage ist: Wie verhindert dieser Index die Verwendung eines anderen Index? –

+2

Ihre Statistiken auf Ihren Tabellen sind möglicherweise veraltet. –

Verwandte Themen