Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Dziwne zmiany prędkości z zapytaniem sql

Aby lepiej zrozumieć, co się dzieje, wypróbuj to:

explain plan set statement_id = 'query1' for
SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5
     AND ck.prgrm_id = 1;

a następnie:

select *
from table(dbms_xplan.display(statement_id=>'query1'));

Domyślam się, że zobaczysz linię wskazującą PEŁNY DOSTĘP DO TABELI na klawiszu claim_key.

Następnie spróbuj:

explain plan set statement_id = 'query2' for
SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5;

select *
from table(dbms_xplan.display(statement_id=>'query2'));

i sprawdź, jakiego indeksu (prawdopodobnie) używa. To powinno dać ci wyobrażenie o tym, co robi baza danych, co pomaga dowiedzieć się, dlaczego robi to.

Ok, biorąc pod uwagę twoje plany wyjaśnień, jest to klasyczny przykład „indeksy nie zawsze są dobre, a skanowanie tabel nie zawsze jest złe”.

INDEX SKIP SCAN to miejsce, w którym baza danych może próbować użyć indeksu, nawet jeśli wiodąca kolumna indeksu nie jest nawet używana. Zasadniczo, jeśli Twój indeks wyglądał tak (zbyt uproszczony):

COL1   COL2   ROWID
A      X      1        <--
A      Y      2
A      Z      3
B      X      4        <--
B      Y      5
B      Z      6 

a twój warunek to WHERE col2 ='X' indeks pomijania skanowania mówi przejrzeć każdą kombinację w COL1 dla gdzie col2 ='X'. „Pomija” wartości w col1 po znalezieniu dopasowania (np. col1 =A, col2 =X) do miejsca, w którym zmienia się wartość (col1 =B, następnie col1 =C itd.) i szuka więcej dopasowań.

Połów polega na tym, że indeksy (ogólnie!) działają w ten sposób:1) znajdź następny wierszid w indeksie, w którym znaleziono wartość2) przejdź do bloku tabeli z tym wierszem (TABLE ACCESS BY INDEX ROWID)3) powtarzaj, aż nie będzie więcej dopasowań zostały znalezione.

(W przypadku pomijania skanu wiązałoby się to również z kosztami ustalenia, gdzie znajduje się następna zmiana wartości dla wiodących kolumn.)

To wszystko jest dobre i dobre dla małej liczby rzędów, ale cierpi z powodu prawa malejących zysków; to nie jest takie wspaniałe, gdy masz dużą liczbę wierszy. Dzieje się tak dlatego, że musi odczytać blok indeksu, potem blok tabeli, potem blok indeksu, blok tabeli (nawet jeśli blok tabeli został wcześniej odczytany).

Skanowanie całego stołu po prostu „przedziera się” przez dane, po części dzięki… odczytom wieloblokowym. Baza danych może odczytać wiele bloków z dysku w jednym odczycie i nie odczytuje tego samego bloku więcej niż raz.

INDEX FAST FULL SCAN zasadniczo traktuje I_CLAIM_KEY_002 jako tabelę. Na wszystko, czego potrzebujesz w zapytaniu, odpowiada sam indeks; DOSTĘP DO TABEL nie jest wymagany. (Zgaduję, że I_CLAIM_KEY_002 jest zdefiniowany jako clnt_id, dte_of_srvce i albo clnt_id, albo dte_of_srvce nie dopuszcza wartości null. Ponieważ ck.id powinien być atrybutem innym niż null, licznik na ck.id jest taki sam jak licznik na ck.clnt_id.)

Więc jeśli chodzi o początkowe zapytanie, jeśli nie chcesz zmienić indeksów, wypróbuj to:

SELECT  /*+ FULL(ck) */ count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5
     AND ck.prgrm_id = 1

co wymusi pełne skanowanie tabeli na claim_key (ck) i możesz zobaczyć podobną wydajność jak pozostałe dwa. (Sprawdź, czy tak jest, najpierw poprzedź zapytanie „explain plan statement_id ='query_hint' for” i uruchom zapytanie dbms_xplan przed jego uruchomieniem.)

(Teraz zapytasz "czy chcę wstawiać takie wskazówki przez cały czas"? Proszę tego nie robić. To jest tylko dla testu. To jest tylko sprawdzenie, czy FTS jest lepszy niż INDEX SKIP SCAN . Jeśli tak, to musisz dowiedzieć się dlaczego :)

W każdym razie... mam nadzieję, że to zrobiło snese... mam na myśli sens.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak za pomocą zapytania uzyskać listę miesięcy pomiędzy 2 podanymi datami?

  2. 2 funkcje, które zwracają miesiąc z daty w Oracle

  3. Jak wstawić zestaw wyników zwrócony przez procedurę składowaną Oracle do innej tabeli przy użyciu drugiej procedury składowanej?

  4. APEX:Pobierz BLOB z tabeli tymczasowej

  5. Po upuszczeniu partycji indeks stał się bezużyteczny, co mam zrobić,