2009-08-25 15 views
23

Mam zapytanie jakoracle DELETE biorąc zbyt dużo czasu

DELETE from tablename where colname = value; 

który trwa strasznie długo, aby wykonać. Jaki może być tego powód? Mam indeks na colname.

+0

Czy możesz opublikować plan wyjaśniający zapytanie (w SQL * Plus, uruchom "SET AUTOTRACE ON EXPLAIN", a następnie zapytanie)? –

+0

SQL> ustaw autotrace na objaśnienie SQL> usuń z nazwy tabeli, gdzie nid = 1250626; Usunięto 1 wiersz. Plan wykonania ------------------------------------------------ ---------- 0 USUŃ STATUSU Optymalizator = ALL_ROWS (Koszt = 2 Card = 1 Bytes = 48) 1 0 USUŃ "tablename" 2 1 INDEX (UNIQUE SCAN) OF "PK_tablename" (INDEX (UNIQUE)) (Koszt = 1 karta = 1 bajt = 48) Służy to do usuwania 1 wiersza. Oryginalne zapytanie ma warunek "> =", który nie mógł być zakończony do około 20 minut. Nawet z "=", zajmuje to więcej niż minutę. – Ajay

+0

Co powiesz na wydajność * WYBIERZ * Z nazwy pliku WHERE nid = 1250626; *? – Christian13467

Odpowiedz

30

Nie może być kilka wyjaśnień, dlaczego zapytanie trwa długo:

  1. Można być zablokowany przez inną sesję (najprawdopodobniej). Przed usunięciem należy upewnić się, że nikt inny nie blokowania wierszy, np: problem SELECT NULL FROM tablename WHERE colname=:value FOR UPDATE NOWAIT,
  2. Nie może być ON DELETE TRIGGER które wykonuje dodatkową pracę,
  3. Sprawdź UNINDEXED REFERENCE CONSTRAINTS wskazując na tej tabeli (jest script from AskTom które pomogą określasz, czy istnieją takie nieindeksowane klucze obce).
+0

dzięki za odpowiedź, ale nie opcje 1 i 2. – Ajay

+2

Trzeci był w rzeczywistości rozwiązaniem :). Teraz wykonuje się w ciągu 2 sekund! – Ajay

+0

cieszymy się z pomocy =). Właściwie powinienem był umieścić trzeci punkt w miejscu numer jeden, ponieważ jest to najbardziej prawdopodobne, że zostanie przeoczony. –

4

Może to oznaczać, że stolik jest powiązany z wieloma stołami i ma dużą liczbę wierszy.

+0

tak. poprawny! To był ogromny stół dla rodziców – Ajay

2

Jak selektywny jest ten indeks? Jeśli twoja tabela ma milion wierszy, a ta wartość trafia sto pięćdziesiąt tysięcy z nich, twój indeks jest bezużyteczny. W rzeczywistości może być gorszy niż bezużyteczny, jeśli jest faktycznie używany. Pamiętaj, że DELETE jest jak instrukcja SELECT: możemy dostroić swoją ścieżkę dostępu.

Usunięcia zajmuje również wiele tabel zmian, więc możesz mieć problemy z rywalizacją, jeśli system jest intensywnie wykorzystywany. W systemie wieloużytkownikowym inna sesja może blokować wiersze, które chcesz usunąć.

Czy masz wyzwalacze ON DELETE? Czy masz ograniczenia na klucz obcy na CASE DELETE CASCADE?

Edit: Biorąc pod uwagę wszystko, co mówisz, a zwłaszcza kolumna w pytaniu jest kluczem podstawowym, więc starają się usunąć pojedynczy wiersz, jeśli jest to zajmuje dużo czasu jest o wiele bardziej prawdopodobne, że jakiś inny proces lub użytkownik ma blokadę w rzędzie. Czy coś pojawia się w V$LOCK?

+0

Nie Włącz kasowanie wyzwalaczy. Tabela ma więcej niż 1 milion wierszy. Indeksowana kolumna jest kluczem podstawowym. NIE WŁAŻAJ ograniczeń KASKADY. Mam kolejną tabelę nadrzędną z> 1 milionem wierszy, która zajmuje tylko sekundę, aby usunąć wiersz! – Ajay

0

Czy Twoja tabela zawiera więcej rekordów?
Czy na serwerze bazy danych działają niektóre programy rekurencyjne (niektóre zagnieżdżone pętle itp.)?
Sprawdź problemy sieciowe, jeśli serwer bazy danych znajduje się na różnych komputerach?

+0

Brak rekurencyjnego pgms po stronie serwera. Bez błędu n/w – Ajay

0

Więc ja po prostu pisać moje doświadczenie. Może być pomocny dla kogoś.

Zapytanie

delete from foo 
where foo_id not in ( 
    select max(foo_id) from foo group by foo_bar_id, foo_qux_id 
); 

trwało 16 sekund. usunięcie 1700 rekordów z 2300 razem w tabeli foo.

Sprawdziłem wszystkie indeksy kluczy obcych zgodnie z innymi odpowiedziami. To nie pomogło.

Rozwiązanie:

Zmieniono zapytanie do

delete from foo 
where foo_id in ( 
    select foo_id from foo 
    minus 
    select max(foo_id) from foo group by foo_bar_id, foo_qux_id 
); 

Zmieniłem not in do in i używane minus osiągnąć prawidłowy wynik.

Teraz zapytanie wykonuje się w 0,04 sek.

Powiązane problemy