sql >> Databasteknik >  >> RDS >> Oracle

där rownum=1 fråga tar tid i Oracle

Den här frågan har redan besvarats, jag ska bara ge en förklaring till varför ibland ett filter ROWNUM=1 eller ROWNUM <=1 kan resultera i lång svarstid.

När du stöter på ett ROWNUM-filter (på en enda tabell), kommer optimeraren att producera en FULLSTÄNDIG SCANNING med COUNT STOPKEY. Det betyder att Oracle börjar läsa rader tills det möter de första N raderna (här N=1). En fullständig skanning läser block från den första utsträckningen till högvattenmärket. Oracle har inget sätt att avgöra vilka block som innehåller rader och vilka som inte gör det i förväg, alla block kommer därför att läsas tills N rader hittas. Om de första blocken är tomma kan det resultera i många läsningar.

Tänk på följande:

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

Som du kan se är antalet konsekventa gets extremt högt (för en enda rad). Denna situation kan uppstå i vissa fall där du till exempel infogar rader med /*+APPEND*/ ledtråd (alltså över högvattenmärket), och du raderar också de äldsta raderna med jämna mellanrum, vilket resulterar i mycket tomt utrymme i början av segmentet.



  1. Hur man hämtar uppladdade filer med php

  2. Ta med ditt eget moln tillgängligt för DigitalOcean

  3. konvertera sql server rowversion till long eller ulong?

  4. Hur man anropar en funktion med parametern Rowtype från en select-sats i Oracle