sql >> Database >  >> RDS >> Oracle

Vreemde snelheidsveranderingen met sql-query

Probeer dit om beter te begrijpen wat er aan de hand is:

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;

en dan:

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

Ik vermoed dat je op claim_key een regel ziet die aangeeft TABLE ACCESS FULL.

Probeer dan:

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'));

en controleer om te zien welke index het (vermoedelijk) gebruikt. Dat zou je een idee moeten geven van wat de database doet, wat helpt om erachter te komen waarom het doet het.

Ok, gezien je uitlegplannen, is dit een klassiek voorbeeld van "indexen zijn niet altijd goed, tabellenscans zijn niet altijd slecht".

De INDEX SKIP SCAN is waar de database kan proberen een index te gebruiken, ook al wordt de leidende kolom van de index niet eens gebruikt. Als uw index er ongeveer zo uitzag (overdreven vereenvoudigd):

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

en uw toestand was WHERE col2 ='X', de scan voor het overslaan van de index zegt dat u door elke combinatie in COL1 moet kijken voor waar col2 ='X'. Het "slaat" de waarden in col1 over zodra er een overeenkomst is gevonden (bijv. col1 =A, col2 =X) tot waar de waarde verandert (col1 =B, dan col1 =C, enz.) en zoekt naar meer overeenkomsten.

De vangst is dat indexen (over het algemeen!) als volgt werken:1) zoek de volgende rowid in de index waar de waarde is gevonden2) ga naar het tabelblok met die rowid (TOEGANG TABLE BY INDEX ROWID)3) herhaal totdat er geen overeenkomsten meer zijn zijn gevonden.

(Voor de scan overslaan zou het ook de kosten met zich meebrengen om uit te zoeken waar de volgende waardeverandering is voor de leidende kolommen.)

Dit is allemaal goed en wel voor een klein aantal rijen, maar lijdt onder de wet van de afnemende meeropbrengst; het is niet zo geweldig als je een groot aantal rijen hebt. Dat komt omdat het een indexblok moet lezen, dan een tabelblok, dan een indexblok, een tabelblok (zelfs als het tabelblok eerder is gelezen.)

De volledige tabelscan "ploegt" gewoon door de gegevens, mede dankzij ... multiblock-lezingen. De database kan in één keer veel blokken van schijf lezen en leest hetzelfde blok niet meer dan één keer.

De INDEX FAST FULL SCAN behandelt in feite de I_CLAIM_KEY_002 als een tabel. Alles wat je nodig hebt in de query kan alleen door de index worden beantwoord; er is geen TAFELTOEGANG vereist. (Ik gok dat I_CLAIM_KEY_002 is gedefinieerd als clnt_id, dte_of_srvce en clnt_id of dte_of_srvce is niet nullable. Aangezien ck.id een niet-null-attribuut zou moeten zijn, is een telling op ck.id hetzelfde als een telling op ck.clnt_id.)

Dus wat betreft uw eerste vraag, probeer dit, tenzij u uw indexen wilt herschikken:

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

wat een volledige tabelscan op claim_key (ck) zal forceren en je zou vergelijkbare prestaties kunnen zien als de andere twee. (Controleer of dit het geval is door eerst de query vooraf te laten gaan met "explain plan set statement_id ='query_hint' for" en de dbms_xplan-query uit te voeren voordat u deze uitvoert.)

(Nu zul je vragen "wil ik altijd zulke hints invoeren"? Doe dit alsjeblieft niet. Dit is alleen voor een test. Dit is alleen om te controleren of een FTS beter is dan de INDEX SKIP SCAN Als dat zo is, moet je uitzoeken waarom. :)

Hoe dan ook ... ik hoop dat het logisch was ... ik bedoel logisch.



  1. Is het mogelijk om een ​​database te doorzoeken met behulp van een waarde die in een URL is doorgegeven, en het resultaat van de query naar de URL te schrijven met mod_rewrite?

  2. Hoe u optimaal gebruik kunt maken van de commentaarfunctie in MySQL

  3. XMLTABLE in PostgreSQL

  4. RefCursor- en VarChar-uitvoer verkrijgen uit dezelfde opgeslagen procedure