2011-02-10 20 views
7
UPDATE table1 
     SET col1 = 'Y' 
    WHERE col2 in (select col2 from table2) 

W powyższym zapytaniu wyobraź sobie, że zapytanie wewnętrzne zwraca 10000 wierszy. Czy to zapytanie z klauzulą ​​IN ma wpływ na wydajność?W jaki sposób klauzula IN wpływa na wydajność w Oracle?

Jeśli tak, co można zrobić, aby przyspieszyć wykonanie?

+0

Jeśli sub-zapytanie zwróci 10000 wyników runtime będzie zerowy, ponieważ zgłasza błąd. Zakładam, że chcesz napisać IN zamiast = dla podselekcji? –

+0

Masz to. Dokonałem zmiany, dziękuję. – Vivek

+1

, jeśli odpowiedź udzielona przez @zerkms była dla Ciebie pomocna, zaakceptuj to. Sprawdź FAQ, aby dowiedzieć się, dlaczego powinieneś to zrobić. :-) –

Odpowiedz

3
UPDATE table1 outer 
    SET col1 = 'Y' 
WHERE EXISTS (select null 
       from table2 
       WHERE col2 = outer.col2) 

To może być lepiej

Aby uzyskać pomysł co jest lepsze - spojrzeć na plan wykonania.

+2

Pomyślałem, że to był problem rozwiązany, ponieważ dla optymalizatora Oracle zwykle nie ma różnicy między IN a EXISTS, a jeden zostanie przekonwertowany na drugi, w zależności od potrzeb. http://blogs.oracle.com/optimizer/2010/09/optimizer_transformations_subquery_unesting_part_1.html –

11

gdy podzapytanie zwraca dużą liczbę wierszy w porównaniu do liczby wierszy w Tabela 1, optymalizator będzie prawdopodobnie stworzenie planu tak:

-------------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time 
-------------------------------------------------------------------------------- 
| 0 | UPDATE STATEMENT |  | 300K| 24M|  | 1581 (1)| 00:0 
| 1 | UPDATE    | TABLE1 |  |  |  |   | 
|* 2 | HASH JOIN SEMI |  | 300K| 24M| 9384K| 1581 (1)| 00:0 
| 3 | TABLE ACCESS FULL| TABLE1 | 300K| 5860K|  | 355 (2)| 00:0 
| 4 | TABLE ACCESS FULL| TABLE2 | 168K| 10M|  | 144 (2)| 00:0 
-------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 
    2 - access("COL2"="COL2") 

będzie skanować obie tabele raz i aktualizować tylko wiersze w TABELA1 wspólny dla obu tabel. Jest to bardzo wydajny plan, jeśli trzeba zaktualizować wiele wierszy.

Czasami zapytanie wewnętrzne będzie miało kilka wierszy w porównaniu do liczby wierszy w TABELA1. Jeśli indeks na TABLE1(col2), można wtedy uzyskać plan podobny do tego:

------------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------- 
| 0 | UPDATE STATEMENT  |  | 93 | 4557 | 247 (1)| 00:00:03 | 
| 1 | UPDATE    | TABLE1 |  |  |   |   | 
| 2 | NESTED LOOPS  |  | 93 | 4557 | 247 (1)| 00:00:03 | 
| 3 | SORT UNIQUE  |  | 51 | 1326 | 142 (0)| 00:00:02 | 
| 4 |  TABLE ACCESS FULL| TABLE2 | 51 | 1326 | 142 (0)| 00:00:02 | 
|* 5 | INDEX RANGE SCAN | IDX1 |  2 | 46 |  2 (0)| 00:00:01 | 
------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 
    5 - access("T1"."COL2"="T2"."COL2") 

W tym przypadku Oracle będzie czytać wiersze z Table2 i dla każdego (unikalne) rzędu, wykonać dostęp indeksu na tabela1 .

Który dostęp jest szybszy, zależy od selektywności zapytania wewnętrznego i grupowania indeksu na TABELĘ 1 (czy wiersze o podobnej wartości wynoszą col2 w TABELI 1 obok siebie lub losowo rozłożone?). W każdym razie, jeśli chodzi o wydajność, jeśli chcesz wykonać tę aktualizację, to jest to jedna z najszybszych metod.

+0

Co z moim zapytaniem?;-) Proszę dodać plan wykonania dla jednego z 'EXISTS' – zerkms

+3

@zerkms: przepraszam Zapomniałem wspomnieć, że podzapytania IN są przekształcane na równoważne podzapytania EXIST przez optymalizator. W związku z tym wytwarzają ten sam plan. Osobiście uważam, że instrukcje IN są bardziej czytelne, ale jest to wysoce subiektywne :) –

+0

nie wiedziałem, dzięki. – zerkms

2

z Oracle:

11.5.3.4 Użycie EXISTS kontra IN dla Podzapytania

w pewnych okolicznościach, to lepiej do wykorzystania w raczej niż istnieje. Jeśli chodzi o ogólne , jeśli predykat selektywny to w podzapytaniu, użyj IN. Jeśli predykat selektywny znajduje się w zapytaniu nadrzędnym , użyj EXISTS.

Z mojego doświadczenia wynika, że ​​widziałem lepsze plany, używając EXISTS, gdzie podzapytanie zwraca dużą liczbę wierszy.

Zobacz here więcej dyskusji z Oracle

Powiązane problemy