sql >> Database >  >> RDS >> Oracle

waarbij rownum=1 query tijd kost in Oracle

Deze vraag is al beantwoord, ik zal alleen uitleggen waarom een ​​filter ROWNUM=1 of ROWNUM <=1 soms kan resulteren in een lange reactietijd.

Wanneer een ROWNUM-filter wordt aangetroffen (op een enkele tabel), produceert de optimizer een VOLLEDIGE SCAN met COUNT STOPKEY. Dit betekent dat Oracle rijen begint te lezen totdat het de eerste N rijen tegenkomt (hier N=1). Een volledige scan leest blokken van de eerste omvang tot de hoogwaterlijn. Oracle heeft geen manier om vooraf te bepalen welke blokken rijen bevatten en welke niet, daarom worden alle blokken gelezen totdat N rijen zijn gevonden. Als de eerste blokken leeg zijn, kan dit resulteren in veel leesacties.

Overweeg het volgende:

SQL> /* rows will take a lot of space because of the CHAR column */
SQL> create table example (id number, fill char(2000));

Table created

SQL> insert into example 
  2     select rownum, 'x' from all_objects where rownum <= 100000;

100000 rows inserted

SQL> commit;

Commit complete

SQL> delete from example where id <= 99000;

99000 rows deleted

SQL> set timing on
SQL> set autotrace traceonly
SQL> select * from example where rownum = 1;

Elapsed: 00:00:05.01

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=7 Card=1 Bytes=2015)    
   1    0   COUNT (STOPKEY)
   2    1     TABLE ACCESS (FULL) OF 'EXAMPLE' (TABLE) (Cost=7 Card=1588 [..])

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      33211  consistent gets
      25901  physical reads
          0  redo size
       2237  bytes sent via SQL*Net to client
        278  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

Zoals je kunt zien, is het aantal consistente slagen extreem hoog (voor een enkele rij). Deze situatie kan zich voordoen in sommige gevallen waar u bijvoorbeeld rijen invoegt met de /*+APPEND*/ hint (dus boven de hoogwaterlijn), en je verwijdert ook regelmatig de oudste rijen, wat resulteert in veel lege ruimte aan het begin van het segment.



  1. Verbinding maken met een MySQL-database met behulp van Xcode en Objective-C

  2. Django-implementatie van standaardwaarde in database

  3. Een trigger gebruiken om een ​​beperking voor een externe sleutelcontrole te implementeren

  4. MySQL:Hoe kan ik de tijdstempel van de laatste invoeging in de database krijgen?