关于consistent gets

简介: 在sql调优的时候,一个关键指标就是consistent gets,如果这个指标很低,一般认为sql语句执行还是很高效的,反之效率会很低。但是这个指标我们知之甚少,对于这个指标的计算方式我们也是懵懵懂懂。
在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






目录
相关文章
|
存储 Java Android开发
Android系统升级的机制概要
Android系统升级的机制概要
512 0
|
数据可视化 大数据 数据挖掘
阿里云大数据ACA及ACP复习题(81~90)
本人备考阿里云大数据考试时自行收集准备的题库,纯手工整理的,能够覆盖到今年7月份,应该是目前最新的,发成文章希望大家能一起学习,不要花冤枉钱去买题库背了,也希望大家能够顺利通关ACA和ACP考试。
使用OpenDaylight界面下发流表(下)
使用OpenDaylight界面下发流表(下)
486 0
|
8月前
|
弹性计算 安全 Linux
课时3:第3天:云服务器最基本操作——实例管理
大家好,欢迎收看玩转云服务器 ECS 系列课程,今天我们来学习第三课:云服务器最基本操作——实例管理。本节课程分为五个小结。 1. 实例有什么用? 2. 创建并登录实例 3. 启动与停止实例 4. 配置的升级与降级 5. 更换操作系统
168 0
基于DSP的数字滤波器设计
基于DSP的数字滤波器设计
442 4
|
10月前
|
人工智能 运维 安全
AI 驱动,全面升级!操作系统服务套件体验评测
作为一名运维工程师,我体验了阿里云的操作系统服务套件,选择了Alibaba Cloud Linux作为测试环境。通过安装SysOM和OS Copilot组件,轻松管理集群健康数据、进行系统诊断并获得优化建议。OS Copilot智能解答技术问题,节省查阅资料时间;订阅管理帮助我及时升级操作系统,保障安全。整体功能强大,提升了约20%的工作效率,值得推广。建议增加更多系统版本支持及自动优化功能。
|
安全 Android开发 iOS开发
深入探讨Android与iOS操作系统的差异性
本文旨在通过对比分析Android和iOS两大主流移动操作系统,揭示它们在设计理念、用户体验、安全性、应用生态及系统更新等方面的根本差异。不同于传统的功能列表式摘要,本摘要强调了两大系统背后的哲学思想及其对用户日常使用的实际影响,为读者提供了一个宏观且深入的视角来理解这两种操作系统的独特之处。
|
11月前
|
数据采集 人工智能 安全
代理IP与人工智能的融合发展
在科技飞速发展的今天,代理IP与人工智能(AI)正以前所未有的速度融合发展,为网络生活带来巨大变化。代理IP通过隐藏真实IP、绕过网络限制、提高访问速度和增强安全性,为AI系统提供了高效的数据访问方式。AI则通过模拟和扩展人的智能,广泛应用于医疗、金融、交通等领域,提高生产效率和生活质量。两者结合,不仅提升了数据采集、处理和模型训练的效率,还为未来创新和发展带来了无限可能。
224 0
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的豆瓣电影数据分析可视化系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的豆瓣电影数据分析可视化系统附带文章源码部署视频讲解等
197 0
三对角矩阵(Triangular Matrix)
三对角矩阵(Triangular Matrix)是一种特殊形式的矩阵,其非零元素仅位于主对角线以及主对角线两侧的相邻对角线上。三对角矩阵在数学、工程和计算机科学等领域中都有广泛应用,特别是在线性代数中。以下是一些关于三对角矩阵的特点和应用:
1707 6