zoukankan      html  css  js  c++  java
  • Asktom:Thanks for the question regarding "consistent gets Very puzzling".

    You Asked

    Tom:
    
    create table test( a int);
    begin
    for i in 1..10000 loop
    insert into test values (i);
    end loop;
    end;
    
    set autotrace on
    select count(0) from test;
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE
       1    0   SORT (AGGREGATE)
       2    1     TABLE ACCESS (FULL) OF 'TEST'
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              4  db block gets
             20  consistent gets
              0  physical reads
              0  redo size
            369  bytes sent via SQL*Net to client
            425  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              1  rows processed
    
    
    select * from test where a=10;
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE
       1    0   TABLE ACCESS (FULL) OF 'TEST'
    
    
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              4  db block gets
             21  consistent gets
              0  physical reads
              0  redo size
            360  bytes sent via SQL*Net to client
            425  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              1  rows processed
    
    
    select * from test;
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE
       1    0   TABLE ACCESS (FULL) OF 'TEST'
    
    
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              4  db block gets
            686  consistent gets
              0  physical reads
              0  redo size
         185864  bytes sent via SQL*Net to client
          74351  bytes received via SQL*Net from client
            668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          10001  rows processed
    
    
    
    question:
    1.
    when query count(0), what exactly did oracle do? since we don't have index, did oracle 
    went to every block and query the number?
    if so, why consistent gets is much lower that select * from test?
    both are full scan table.
    
    2.
    why select * from test have much higher consistent gets than
    select * from test where a=10?
    since there are no index, oracle need to go to every block to get the value, it should be 
    same consistent gets, although the first one return more rows, but it does't matter.
    
    Regards,
    
     

    and we said...

    q1) select count(0) is just like 
    
    select count(*)
      from ( select 0 from t )
    /
    
    yes, oracle went to each block to find the rows to give you a zero
    
    q2) its a side effect of your arraysize.  You must have an 8k blocksize cause I 
    reproduced this exactly.
    
    We were expecting about 20 consistent gets right?  Well, the default array size in 
    sqlplus is 15 rows / fetch.  10000/15 = 666.66666.  Well, 666+20 = 686 -- whoah there -- 
    686 is our consistent gets!
    
    Thats what happened.  When you fetched 15 rows, Oracle paused, gave you the data.  When 
    you went back to get the next 15, it got the buffer again to resume your query. 
    
    Watch what happens with different array sizes, starting with 15:
    
    
    ops$tkyte@8i> select * from test;
    
    10000 rows selected.
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              4  db block gets
            686  consistent gets
              0  physical reads
              0  redo size
         108813  bytes sent via SQL*Net to client
          46265  bytes received via SQL*Net from client
            668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          10000  rows processed
    
    ops$tkyte@8i> set arraysize 1000
    ops$tkyte@8i> select * from test;
    
    10000 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              4  db block gets
             30  consistent gets
              0  physical reads
              0  redo size
          86266  bytes sent via SQL*Net to client
            942  bytes received via SQL*Net from client
             11  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          10000  rows processed
    
    ops$tkyte@8i> set arraysize 5000
    ops$tkyte@8i> select * from test;
    
    10000 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              4  db block gets
             22  consistent gets
              0  physical reads
              0  redo size
         149793  bytes sent via SQL*Net to client
            382  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          10000  rows processed
    
    
    
    Other interesting thing to note is that as the array size gets too large -- the amount of 
    data transferred goes up.  there is a diminishing marginal return on the array size so 
    don't go OVERBOARD.
    
    followup to comment one
    
    Set the arraysize to some constant as it will not matter for single row fetches whether 
    it is too big but having it too small for lots of rows (NOT just full scans -- lots of 
    rows) does impact you.
    
    I am a bit confused now, though you explained it well, but I tested it in my envirnment and got 
    different results.
    My query returns 122 rows with a select *.
    
    Arraysize of 15 --> number of consistent gets was=1051 (122/15=8) which means 1043 + 8 = 1051 (good 
    so far)
    so I would assume according to the example above that when I do count(*) number of consistent gets 
    would be 1043, right? BUT 
    Arrayszie of 15 with count(*) --> consistent gets = 920 I dont understand where this comes from?
    
    I did more testing:
    Arraysize of 122 with select * --> consistent gets = 1043
    Arraysize of 122 with select count(*) --> consistent gets = 920
    
    Arrayszie of 5000 with select * --> consistent gets = 1043
    Arrayszie of 5000 with select count(*) --> consistent gets = 920
    
    I would appreciate if you can explain.
    thanks,
    ZS
     


    Followup May 1, 2002 - 7am Central time zone:

    The count(*) returns how many rows?  1.
    
    The array size does even begin to kick in.  That statement is processed in ONE call.
    
    Also, the count(*) may very well *never be touching the table*.  It might be just using an index.
    
    Consider:
    
    ops$tkyte@ORA817DEV.US.ORACLE.COM> create table t as select * from all_objects;
    
    Table created.
    
    ops$tkyte@ORA817DEV.US.ORACLE.COM> 
    ops$tkyte@ORA817DEV.US.ORACLE.COM> 
    ops$tkyte@ORA817DEV.US.ORACLE.COM> exec show_space( 'T' )
    Free Blocks.............................0
    Total Blocks............................320
    Total Bytes.............................2621440
    Unused Blocks...........................4
    Unused Bytes............................32768
    Last Used Ext FileId....................7
    Last Used Ext BlockId...................40969
    Last Used Block.........................60
    
    PL/SQL procedure successfully completed.
    
    so the table consumes about 316 blocks..
    
    
    ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from t;
    22905 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
             12  db block gets
           1823  consistent gets
             46  physical reads
              0  redo size
        2704019  bytes sent via SQL*Net to client
         169811  bytes received via SQL*Net from client
           1528  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          22905  rows processed
    
    
    22905/15 = 1527+316 = 1843 which is about our consistent gets (what we were expecting)....
    
    ops$tkyte@ORA817DEV.US.ORACLE.COM> select count(*) from t;
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
             12  db block gets
            319  consistent gets
             46  physical reads
              0  redo size
            369  bytes sent via SQL*Net to client
            425  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              1  rows processed
    
    And the count(*), since it was done in a SINGLE CALL -- no arraysize -- only did a consistent get 
    on each block ONE TIME.  Hence it did 319 consistent gets (which is about the size of the table)
    
    Now, adding a primary key to the table:
    
    
    ops$tkyte@ORA817DEV.US.ORACLE.COM> alter table t add constraint t_pk primary key(object_id);
    
    Table altered.
    
    ops$tkyte@ORA817DEV.US.ORACLE.COM> analyze table t compute statistics;
    
    Table analyzed.
    
    ops$tkyte@ORA817DEV.US.ORACLE.COM> select count(*) from t;
    
    
    Statistics
    ----------------------------------------------------------
             79  recursive calls
              4  db block gets
             82  consistent gets
              1  physical reads
              0  redo size
            369  bytes sent via SQL*Net to client
            425  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
              1  rows processed
    
    we can see that the consistent gets go way down.  why?  because the optimizer counted the rows in 
    the index, not the table in this case.
    
    
     
     
  • 相关阅读:
    使用git笔记
    linux 进程管理的一些命令使用
    [zz]XML DOM 教程
    [zz]std::string 和 c 的字符串
    [zz]grep 命令的使用
    [zz]XercesC++ 参考
    [zz]Windows WordPress本地安装教程
    今天调出来的关于cello的bug
    shell 编程的一些问题
    关于java中边界值校验的问题
  • 原文地址:https://www.cnblogs.com/tracy/p/2132519.html
Copyright © 2011-2022 走看看