sql >> Databáze >  >> RDS >> Oracle

kde rownum=1 dotaz zabírá čas v Oracle

Tato otázka již byla zodpovězena, pouze poskytnu vysvětlení, proč někdy může filtr ROWNUM=1 nebo ROWNUM <=1 způsobit dlouhou dobu odezvy.

Když narazí na filtr ROWNUM (na jedné tabulce), optimalizátor vytvoří FULL SCAN s COUNT STOPKEY. To znamená, že Oracle začne číst řádky, dokud nenarazí na prvních N řádků (zde N=1). Úplné skenování čte bloky od prvního rozsahu až po značku nejvyšší hladiny. Oracle nemá žádný způsob, jak předem určit, které bloky obsahují řádky a které ne, všechny bloky budou proto čteny, dokud nebude nalezeno N řádků. Pokud jsou první bloky prázdné, může to mít za následek mnoho čtení.

Zvažte následující:

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

Jak můžete vidět, počet konzistentních get je extrémně vysoký (pro jeden řádek). K této situaci může dojít v některých případech, kdy například vložíte řádky s /*+APPEND*/ nápověda (tedy nad značkou nejvyšší hladiny) a také pravidelně odstraňujete nejstarší řádky, což má za následek spoustu prázdného místa na začátku segmentu.



  1. Vytvoření tabulky pomocí mysql, php a ajax (s jquery)

  2. Auto-inkrement MySQL mezi tabulkami

  3. GROUP_CONCAT více polí s jiným oddělovačem

  4. SQL Vnitřní spojení na vybraných příkazech