在ORACLE数据库中有物理读(Physical Reads)、逻辑读(Logical Reads)、一致性读(Consistant Get)、当前模式读(DB Block Gets)等诸多概念,若是不理解或混淆这些概念的话,对你深刻理解一些知识无疑是一个障碍,可是这些概念确实挺让让人犯晕的。下面咱们总结、学习一下这方面的知识点。捋一捋他们的关系和特色,但愿对你有所帮助。 sql
物理读(Physical Reads) 数据库
从磁盘读取数据块到内存的操做叫物理读,当SGA里的高速缓存(Cache Buffer)里面不存在这些数据块时,就会产生物理读,另外。像全表扫描、磁盘排序等操做也可能产生物理读,缘由也是由于ORACLE数据库须要访问的数据块较多,而有些数据块不在内存当中,须要从磁盘读取。 编程
逻辑读(Logical Reads) c#
概念1:逻辑读指ORACLE从内存读到的数据块数量。通常来讲, logical reads = db block gets + consistent gets 缓存
概念2:逻辑读指的就是从Buffer Cache中读取数据块。按照访问数据块的模式不一样,能够分为当前模式读(Current Read)和一致性读(Consistent Read)。 session
这两个概念本质是同样的,只是措辞不同。 oracle
一致性读(Consistant Get) app
ORACLE是一个多用户系统。当一个会话开始读取数据还未结束读取以前,可能会有其余会话修改了它将要读取的数据。若是会话读取到修改后的数据,就会形成数据的不一致。一致性读就是为了保证数据的一致性。在Buffer Cache中的数据块上都会有最后一次修改数据块时的SCN。若是一个事务须要修改数据块中数据,会先在回滚段中保存一份修改前数据和SCN的数据块,而后再更新Buffer Cache中的数据块的数据及其SCN,并标识其为“脏”数据。当其余进程读取数据块时,会先比较数据块上的SCN和进程本身的SCN。若是数据块上的SCN小于等于进程自己的SCN,则直接读取数据块上的数据;若是数据块上的SCN大于进程自己的SCN,则会从回滚段中找出修改前的数据块读取数据。一般,普通查询都是一致性读。 ide
当前模式读(DB Block Gets) wordpress
我的以为当前模式读(db block gets)是最难理解的一个概念,一般状况下db block gets 能够理解为是DML操做才会产生的.
当前模式读(db block gets)即读取数据块是当前的最新数据。任什么时候候在Buffer Cache中都只有一份当前数据块。当前读一般发生在对数据进行修改、删除操做时。这时,进程会给数据加上行级锁,而且标识数据为“脏”数据。current mode产生db block gets,通常在DML操做时产生,query mode产生consistent gets(一致性读),通常在查询时产生。他们两个总和通常称为逻辑读,logical read。
有个有意思的现象,在ask tom或一些资料中,你会发现Oracle 8i在SELECT查询当中还能看到db block gets,可是ORACLE 10以及以上版本在SELECT语句中db block gets通常为0。
了解完了概念,若是你仍是有一些疑问和不解,那咱们结合实际例子来理解一下这些概念吧。以下所示:
SQL> show user;
USER is "SYS"
SQL> create table test
2 as
3 select * from dba_objects;
Table created.
SQL> alter session set sql_trace=true;
System altered.
SQL> set autotrace on;
SQL> select object_type, count(1) from test
2 group by object_type;
OBJECT_TYPE COUNT(1)
------------------- ----------
EDITION 1
INDEX PARTITION 264
CONSUMER GROUP 25
SEQUENCE 223
TABLE PARTITION 240
SCHEDULE 3
QUEUE 35
RULE 1
JAVA DATA 328
...............................
...............................
43 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1435881708
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 75101 | 806K| 284 (2)| 00:00:04 |
| 1 | HASH GROUP BY | | 75101 | 806K| 284 (2)| 00:00:04 |
| 2 | TABLE ACCESS FULL| TEST | 75101 | 806K| 281 (1)| 00:00:04 |
---------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
48 recursive calls
0 db block gets
1109 consistent gets
1029 physical reads
0 redo size
1694 bytes sent via SQL*Net to client
545 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
43 rows processed
SQL> select object_type, count(1) from test
2 group by object_type;
OBJECT_TYPE COUNT(1)
------------------- ----------
EDITION 1
INDEX PARTITION 264
CONSUMER GROUP 25
SEQUENCE 223
TABLE PARTITION 240
..............................
..............................
43 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1435881708
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 75101 | 806K| 284 (2)| 00:00:04 |
| 1 | HASH GROUP BY | | 75101 | 806K| 284 (2)| 00:00:04 |
| 2 | TABLE ACCESS FULL| TEST | 75101 | 806K| 281 (1)| 00:00:04 |
---------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1034 consistent gets
0 physical reads
0 redo size
1694 bytes sent via SQL*Net to client
545 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
43 rows processed
SQL> set autotrace off
SQL> alter session set sql_trace =false;
Session altered.
SQL> SELECT T.value
2 || '/'
3 || Lower(Rtrim(I.INSTANCE, Chr(0)))
4 || '_ora_'
5 || P.spid
6 || '.trc' TRACE_FILE_NAME
7 FROM (SELECT P.spid
8 FROM v$mystat M,
9 v$session S,
10 v$process P
11 WHERE M.statistic# = 1
12 AND S.sid = M.sid
13 AND P.addr = S.paddr) P,
14 (SELECT T.INSTANCE
15 FROM v$thread T,
16 v$parameter V
17 WHERE V.name = 'thread'
18 AND ( V.value = 0
19 OR T.thread# = To_number(V.value) )) I,
20 (SELECT value
21 FROM v$parameter
22 WHERE name = 'user_dump_dest') T;
TRACE_FILE_NAME
--------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/gsp/gsp/trace/gsp_ora_24900.trc
如上截图所示, SQL语句第一次执行时,一致性读(consistent gets)为1109, 物理读(physical reads)为1029,当前模式读(db block gets)为0. 若是你再执行一次上面SQL语句,你会发现物理读(physical reads)会下降为0了,由于上一次查询,ORACLE已经将表test的全部数据块读取到buffer cache里面了。固然生产环境实际状况会复杂不少。
咱们先用tkprof工具格式化一下trace文件,而后咱们分析一下 out_24900.prf文件。
[oracle@DB-Server trace]$ tkprof gsp_ora_24900.trc out_24900.prf aggregate=no;
TKPROF: Release 11.2.0.1.0 - Development on Thu Sep 22 10:12:15 2016
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
在分析以前,咱们先了解一下一些概念、术语
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk # 物理读
query = number of buffers gotten for consistent read # 一致性读
current = number of buffers gotten in current mode (usually for update) # 当前模式读
rows = number of rows processed by the fetch or execute call
call:每次SQL语句的处理都分红三个部分
Parse:这步包括语法检查和语义检查(包括检查是否有正确的受权和所须要用到的表、列以及其余引用到的对象是否存在)、以及将SQL语句转换、生成执行计划等。
Execute:这步是真正的由ORACLE来执行语句。对于insert、update、delete操做,这步会修改数据,对于select操做,这步就只是肯定选择的记录。
Fetch:返回查询语句中所得到的记录,这步只有select语句会被执行。
count : 这个语句被parse、execute、fetch的次数。
cpu :这个语句对于全部的parse、execute、fetch所消耗的cpu的时间,以秒为单位。
elapsed :这个语句全部消耗在parse、execute、fetch的总的时间。
disk :从磁盘上的数据文件中物理读取的数据块的数量。
query :在一致性读模式下,一致性读的数量。
current :在current模式下,即当前模式读下db blocks gets的数量。
rows : 全部SQL语句返回的记录数目,可是不包括子查询中返回的记录数目。对于select语句,返回记录是在fetch这步,对于insert、update、delete操做,返回记录则是在execute这步。
以下截图所示(图1与图2本是链接在一块儿的,因为太长,分开截图,两张图片有相同部分),因为咱们实验过程当中,并无采集统计信息,你会看到trac文件里面有一个动态采样(若是你在建立表,作一次统计信息收集,结果会有一些差异),另外,物理读和一致性读以下,跟上面的执行计划中的数据一致。
disk(物理读) = 747+282 = 1029
query(一致性读) = 1035+74 = 1109
继续分析格式化的prf文件,咱们会看到第二次查询的query(一致性读)为1034, disk(物理读)为0
上面例子,让咱们了解了物理读、一致性读,那么接下来看看当前模式读(db block gets)的例子
SQL> create table t
2 ( id number(10)
3 );
Table created.
SQL> set autotrace on;
SQL> insert into t
2 values(1000);
1 row created.
Execution Plan
----------------------------------------------------------
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | 100 | 1 (0)| 00:00:01 |
| 1 | LOAD TABLE CONVENTIONAL | T | | | | |
---------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
7 db block gets
1 consistent gets
0 physical reads
748 redo size
836 bytes sent via SQL*Net to client
783 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> insert into t
2 values(1001);
1 row created.
Execution Plan
----------------------------------------------------------
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | 100 | 1 (0)| 00:00:01 |
| 1 | LOAD TABLE CONVENTIONAL | T | | | | |
---------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
1 db block gets
1 consistent gets
0 physical reads
308 redo size
837 bytes sent via SQL*Net to client
783 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
一致性读如何计算呢?
关于一致性读如何计算呢? 我查了一下资料,通常一致性读consistent gets ~= numrows/arraysize + blocks ,确切的说是consistent reads计算 ~=ceil(获取行数(card)/arraysize)+used blocks, 并且这个不是绝对等于,而是约等于的关系。 可是这个不是官方资料,而是asktom和一些技术博客的介绍,咱们来验证看看吧
SQL> exec dbms_stats.gather_table_stats(user, 'TEST');
PL/SQL procedure successfully completed.
SQL>
SQL> set autotrace traceonly stat
SQL> select * from test;
72271 rows selected.
Statistics
----------------------------------------------------------
448 recursive calls
0 db block gets
5846 consistent gets
1031 physical reads
0 redo size
8296071 bytes sent via SQL*Net to client
53521 bytes received via SQL*Net from client
4820 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
72271 rows processed
SQL> /
72271 rows selected.
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
5789 consistent gets
0 physical reads
0 redo size
8296071 bytes sent via SQL*Net to client
53521 bytes received via SQL*Net from client
4820 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
72271 rows processed
SQL> set autotrace off;
SQL> set serveroutput on;
SQL> exec show_space('TEST',USER);
Free Blocks............................. 0
Total Blocks............................ 1,152
Total Bytes............................. 9,437,184
Total MBytes............................ 9
Unused Blocks........................... 121
Unused Bytes............................ 991,232
Last Used Ext FileId.................... 1
Last Used Ext BlockId................... 89,344
Last Used Block......................... 7
PL/SQL procedure successfully completed.
SQL> show arraysize ;
arraysize 15
SQL> select ceil(72271/15) + 1152-121 from dual;
CEIL(72271/15)+1152-121
-----------------------
5850
SQL> SELECT COUNT(DISTINCT dbms_rowid.rowid_block_number(ROWID)) AS blocks FROM TEST;
BLOCKS
----------
1030
SQL> SELECT ceil(72271/15) + 1030 FROM DUAL;
CEIL(72271/15)+1030
-------------------
5849
不论是5849仍是5850,都和5879 或5846有一点的出入?也就是说上面那个公式不能用等于号,关于这个,其实在https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:880343948514 里面,你会看到这里介绍的也是一个约等于关系,而不是一个绝对等于的关系。在这里我想深刻一点,无奈知识有限。 从上面的公式, 咱们能够看到一致性读跟arraysize的关系是蛮大的。那么咱们来测试验证一下,先将araraysize调整为50
SQL> set autotrace off;
SQL> set arraysize 50
SQL> set autotrace traceonly stat;
SQL> select * from test;
72271 rows selected.
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2456 consistent gets
0 physical reads
0 redo size
7668743 bytes sent via SQL*Net to client
16418 bytes received via SQL*Net from client
1447 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
72271 rows processed
SQL>
SQL> SELECT ceil(72271/50) + 1030 FROM DUAL;
CEIL(72271/50)+1030
-------------------
2476
SQL>
如上所示,一致性读从5789降为了2456,有兴趣的能够作一下实验。另外,因为在Oracle中,取数据最后都是从buffer cache中取,因此每出现一个physical reads必然会出现一次 logical reads. 也就是说物理读(physical reads)必定小于逻辑读(logical reads=db block gets + consistent gets),也就是说物理读必定小于一致性读,可是也有物理读大于逻辑读的状况,具体参考官方文档 Why Physical Read is greater than Logical Read in Tkprof (文档 ID 211700.1)
PURPOSE
In some circumstances, you can find that tkprof report shows more physical reads than logical reads, which isn't the current result as the physical reads are normally included in logical reads.
SCOPE & APPLICATION
This article will be useful for the DBA's and customers who are concerned by the tuning of Requests.
Why Physical reads are greater than Logical reads
Sometimes, you can find the following content in tkprof report:
· Physical Reads = Disk (total)
· Logical Reads = Query (total) + Current (total)
call |
count |
cpu |
elapsed |
disk |
query |
current |
rows |
------- |
------ |
-------- |
---------- |
---------- |
---------- |
---------- |
---------- |
Parse |
1 |
0.67 |
1.10 |
0 |
0 |
0 |
0 |
Execute |
1 |
0.00 |
0.00 |
0 |
0 |
0 |
0 |
Fetch |
2202 |
167.48 |
678.70 |
579441 |
283473 |
17418 |
33014 |
------- |
------ |
-------- |
---------- |
---------- |
---------- |
---------- |
---------- |
total |
2204 |
168.15 |
679.81 |
579441 |
283473 |
17418 |
33014 |
The 'disk' column is then greater than the 'query' + 'current' columns. This isn't usual.
To find the root cause of the problem, you must generate a 10046 event trace file level 8 and check for direct read waits in it.
In 10046 raw trace, you will find "direct path read" and "direct path write" waits like the example below:
WAIT #1: nam='direct path read' ela= 10076 p1=4 p2=29035 p3=1
with P1 = file#, P2 = start block#, P3 = num blocks
The "direct path read" waits account explains the difference between logical and physical reads.
In Oracle 9.2 and above, TKProf will print waits associated with each SQL statement in the output file.
Explanation:
The reason for more physical reads than logical reads is due to the number of direct reads block access. Direct path reads are generally used by Oracle when reading directly into PGA memory (as opposed to into the buffer cache).
They may happen on different actions:
· Sort IO on disk.
· Read by parallel Query Slaves when scanning is done.
· Blocks read by anticipation (readahead).
Such reads are done without loading blocks into the Buffer Cache. They can be single or multiblock reads.
Utilizing Direct Path Reads in this manner prevents the Oracle Buffer cache from beeing overloaded.
Oracle uses this optimisation when it considers that its not necessary to share the blocks between different sessions.
最后咱们来看一个,热表上一致性读飙涨的案例,其实这个是Oracle 9i&10g编程艺术:深刻数据库体系结构这本书籍里面的一个案例,咱们在此重演一遍,但愿能加深你们对一致性读的理解,首先准备测试数据环境
SQL> show user;
USER is "TEST"
SQL> create table t( x int);
Table created.
SQL> insert into t values(1);
1 row created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(user, 'T');
PL/SQL procedure successfully completed.
SQL> set autotrace on statistics;
SQL> select * from t;
X
----------
1
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
523 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
如上所示,通常状况下一致性读为7,可是咱们在一个会话窗口准备执行下面SQL,频繁修改表T
SQL> begin
2 for i in 1 .. 100000
3 loop
4 update t set x=x+1;
5 commit;
6 end loop;
7 end;
8 /
PL/SQL procedure successfully completed.
在上面会话执行的同时,咱们在另一个会话窗口立刻执行下面SQL,你会看到一致性读飙涨。
SQL> alter session set isolation_level=serializable;
Session altered.
SQL> set autotrace on statistics;
SQL> select * from t;
X
----------
1
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
23681 consistent gets
0 physical reads
0 redo size
523 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
将会话设置为使用SERIALIZABLE 隔离级别,这样不管在会话中运行多少次查询,都将获得事务开始时刻的查询结果。具体分析不在此多此一举,你们感兴趣的能够去看看Oracle9i&10g编程艺术:深刻数据库体系结构。
参考资料:
https://docs.oracle.com/cd/B19306_01/server.102/b14220/consist.htm#i13945
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:880343948514
Oracle 9i&10g编程艺术:深刻数据库体系结构
做者:潇湘隐者
出处:http://www.cnblogs.com/kerrycode/
在sql调优的时候,一个关键指标就是consistent gets,若是这个指标很低,通常认为sql语句执行仍是很高效的,反之效率会很低。可是这个指标咱们知之甚少,对于这个指标的计算方式咱们也是懵懵懂懂。对于逻辑读来讲,通常都是基于Logical Reads= Consistent Gets + DB Block Gets
若是咱们知道logical reads是1000,咱们可能错误地认为查询读取了1000*8k(约为8M)
看了博客https://viveklsharma.wordpress.com/2010/03/04/consistent-gets-myth/后,发现本身的认识是错误的,也按捺不住在本地测试了一把,受益不浅。
首先咱们来建立一个表,数据量为2000条。
n1@TEST11G> create table test_consistent_get as select * from all_objects where rownum between 1 and 2000;
Table created.
而后收集统计信息
n1@TEST11G> exec dbms_stats.gather_table_stats(user,'TEST_CONSISTENT_GET');
PL/SQL procedure successfully completed.
查看相应的数据块为30个
n1@TEST11G> select num_rows,blocks,table_name,last_analyzed,global_stats from user_tables where table_name='TEST_CONSISTENT_GET';
NUM_ROWS BLOCKS TABLE_NAME LAST_ANAL GLO
---------- ---------- ------------------------------ --------- ---
2000 30 TEST_CONSISTENT_GET 20-APR-15 YES
n1@TEST11G> set autot trace
咱们来看看执行计划,很明显走了一个全表扫描。可是咱们须要关注的是统计信息中的consistent gets
n1@TEST11G> select * from test_consistent_get;
Execution Plan
----------------------------------------------------------
Plan hash value: 1444268095
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2000 | 164K| 10 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| TEST_CONSISTENT_GET | 2000 | 164K| 10 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
163 consistent gets
0 physical reads
0 redo size
199754 bytes sent via SQL*Net to client
1883 bytes received via SQL*Net from client
135 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2000 rows processed
能够看到这个表占用的数据块为30,可是consistent gets却为163,很显然不是说这个全表扫描向cache里读入了163*8k的数据
咱们能够经过rowid来获得对应的数据块和其中的数据状况
n1@TEST11G> select dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blkno, count(*) cnt
from test_consistent_get
group by dbms_rowid.ROWID_BLOCK_NUMBER(rowid) order by 1;
BLKNO CNT
---------- ----------
263827 88
263828 84
263829 81
263830 76
263831 81
263832 80
263833 82
263834 77
263835 73
263836 78
263837 79
263838 79
263839 81
263841 82
263842 77
263843 81
263844 80
263845 81
263846 78
263847 78
263848 76
263849 78
263850 78
263851 76
263852 81
263853 15
26 rows selected.
能够经过rowid获得相关的数据块为26个。查看段头,发现对应的数据块是263826是不在上面的rowid对应的数据块范围内的。
n1@TEST11G> select header_block,blocks ,extents from dba_segments where segment_name='TEST_CONSISTENT_GET';
HEADER_BLOCK BLOCKS EXTENTS
------------ ---------- ----------
263826 32 4
对应的区和数据块信息以下:
n1@TEST11G> select EXTENT_ID, FILE_ID, BLOCK_ID, BLOCKS from dba_extents where SEGMENT_NAME='TEST_CONSISTENT_GET';
EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- ---------- ---------- ----------
0 4 263824 8
1 4 263832 8
2 4 263840 8
3 4 263848 8
下面的语句能够算出对于每一个数据块对应的consistent gets的值。
n1@TEST11G>
variable b1 number;
exec :b1:=15;
compute sum of total_cnt on report
compute sum of touch_cnt on report
break on report
select blkno, total_cnt, final_cnt, rows_remaining,
case when rows_remaining=0 then touch_cnt+1 else touch_cnt end touch_cnt
from (
select blkno, total_cnt, final_cnt, rows_remaining,
case when total_cnt = final_cnt then ceil(final_cnt/:b1) else ceil(final_cnt/:b1)+1 end touch_cnt
from (
select blkno, cnt total_cnt,
case when rownum=1 or lag(rows_remaining) over (order by blkno)=0
then cnt else (cnt-(:b1-lag(rows_remaining) over (order by blkno))) end final_cnt,
rows_remaining
from (
select blkno, cnt, rr,
lead(rr) over(order by blkno) next_rr,
lead(blkno) over(order by blkno) next_blk,
ceil(rr/:b1) touch_cnt,
mod(rr,:b1) rows_remaining
from (
select dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blkno, count(*) cnt,
sum(count(*)) over(order by dbms_rowid.ROWID_BLOCK_NUMBER(rowid)) rr
from test_consistent_get
group by dbms_rowid.ROWID_BLOCK_NUMBER(rowid) order by 1))));
BLKNO TOTAL_CNT FINAL_CNT ROWS_REMAINING TOUCH_CNT
---------- ---------- ---------- -------------- ----------
263827 88 88 13 6
263828 84 82 7 7
263829 81 73 13 6
263830 76 74 14 6
263831 81 80 5 7
263832 80 70 10 6
263833 82 77 2 7
263834 77 64 4 6
263835 73 62 2 6
263836 78 65 5 6
263837 79 69 9 6
263838 79 73 13 6
263839 81 79 4 7
263841 82 71 11 6
263842 77 73 13 6
263843 81 79 4 7
263844 80 69 9 6
263845 81 75 0 7
263846 78 78 3 6
263847 78 66 6 6
263848 76 67 7 6
263849 78 70 10 6
263850 78 73 13 6
263851 76 74 14 6
263852 81 80 5 7
263853 15 5 5 2
---------- ----------
sum 2000 159
能够看到对于这个全表扫描的场景,consistent gets不是衡量对于cache的数据块数而是次数。
好比对于上面的数据块 263827 ,数据条数为88条,arraysize为15,则能够简单说明一下是如何计算这个consistent gets值的。
对于数据块263827,放入PGA中,获得了15行,这个时候能够理解为consistent gets=1
对于数据块263827,再次从PGA中获得,获得了15行,这个时候consistent gets=2
依次类推
对于数据块263827,再次从PGA中获得,获得了13行,这个时候consistent gets=6
或者也能够基本按照这个公式来计算,数据行数/arraysize+数据块数=consistent gets
好比这个例子,2000/15+30 大概是163.3左右,因此163仍是靠谱的。
对于arraysize未20,30,的状况下,相应的consistent gets也会减小。简单模拟一下。
n1@TEST11G> set arraysize 20
n1@TEST11G> set autot trace exp stat
n1@TEST11G> select *from test_consistent_get;
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
128 consistent gets
0 physical reads
0 redo size
195334 bytes sent via SQL*Net to client
1509 bytes received via SQL*Net from client
101 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2000 rows processed
n1@TEST11G> set autot off
n1@TEST11G> select 2000/20+30 from dual;
2000/20+30
----------
130
n1@TEST11G> set arraysize 30
n1@TEST11G> set autot trace stat
n1@TEST11G> select *from test_consistent_get;
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
96 consistent gets
0 physical reads
0 redo size
191044 bytes sent via SQL*Net to client
1146 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2000 rows processed
n1@TEST11G> set autot off
n1@TEST11G> select 2000/30+30 from dual;
2000/30+30
----------
96.6666667