buffer cache中的LRU链+
转自晶晶小妹的博客:http://space.itpub.net/13095417/viewspace-204007
一、LRU链介绍
HASH是快速查找时,常用的算法。Oracle中几乎在所有需要快速查找的地方,都使用了HASH算法。LRU则是在“资源重用”时,常用的算法。
在Buffer cache中,LRU链被分为两半,分别是热端、冷端,在默认方式下,热、冷端各占50%的块,这点可以由隐藏参数_db_percent_hot_default控制。当块第一次被读进Buffer时,会被插入到冷端头位置处。每次需要自由块时,Oracle服务器进程从冷端尾开始搜索可以被重用的块,因此,冷端的块是最有可能被重用的。在每个块的Buffer header中,准备有一个量,记录块被访问的次数,称作:Touch Count(TCH)。它代表块的访问频率。Oracle通过它决定块的冷热位置。在DSI中,专门有一段伪码,介绍TCH和块的重用:
关于Touch Count值具体算法如下:
IF ( 当前块的touch count 数> _db_aging_hot_criteria ) THEN
此块暂不重用
IF (_db_aging_stay_count >= _db_aging_hot_criteria) THEN
将此块的Touch Count数减半
ELSE
将此块的Touch Count值传给_db_aging_stay_count
END IF
ELSE
此块将被重用
END IF
(上述伪码来自DSI)
其中,_db_aging_hot_criteria与_ db_aging_stay_count都是Oracle的隐含参数,_db_aging_hot_criteria值默认为2,_ db_aging_stay_count有可能会随时变化。
根据这段代码,假如说,又有新的物理读发生了,Buffer cache中已经没有了空块,服务器进程开始从LRU的冷端开始扫描,寻找可以被重用的自由块。
例如,LRU冷端第一个块的TCH值为4,而当前_db_aging_hot_criteria参数仍为默认值2。因为块的TCH为4,大于2,此块暂不重用。假如_db_aging_stay_count当前值为0,_db_aging_stay_count并不大于等于_db_aging_hot_criteria,因此,将此块的Touch Count值传给_db_aging_stay_count,当前_db_aging_stay_count的值变为了4。
第一个块不可重用,继续向后查找。假如第二个块的TCH也为4,跟据上面的算法,它也不会被重用,但此时由于_db_aging_stay_count的值已经变为了4,已经大于_db_aging_hot_criteria的值2,因此,此块的TCH值将被减半,变为2。
等等,服务器进程照此算法扫描LRU上的块,直到找到足够的自由块为止。
但是这段伪码和我试验的结果一直不符。我试验的结果,每当块的TCH值发生变化时,并不会立即改变它所处的位置。块一旦从冷端移到了热端,TCH值马上变为0。
具体是,服务器进程需要读块进Buffer,它会从LRU链的尾端开始搜索自由块,如果发现搜索到的块的TCH值小于2,就重用这个块,并把它移动到冷端头。如果发现TCH大于2的块,并不会重用它,而是把它移到热端头部,并把它的TCH设为0。下面,我们试验一下这个过程:
-
步1:改变12号文件7号块的TCH值:
先确定一下,此块目前并不在Buffer cache中:
SQL> select lru_flag,tch from x$bh where dbablk=12 and dbarfil=7;未选定行
然后,通过ROWID显示12号文件7号块中的任意一行。(可以只接用ROWID作为条件,也可以使用索引)
SQL> select id from jj_1 where rowid='AAAMt2AAHAAAAAMAAA';ID
----------
1再看一下12号文件7号块的TCH值:
SQL> select lru_flag,tch from x$bh where dbablk=12 and dbarfil=7;LRU_FLAG TCH
---------- ----------
0 1已经是1了。LRU_FLAG列是此块目前在LRU链表中的位置。当此值为8或9时,代表块已经被送进热端。
此时,12号文件7号块当前被添加到了11的位置处:热 端
冷 端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
12/7
TCH:1
每隔三秒,重复执行9遍如下命令:
SQL> select id from jj_1 where rowid='AAAMt2AAHAAAAAMAAB';
ID
----------
8此时12号文件7号块的TCH值应该已经是10了,再显示一下:
SQL> select lru_flag,tch from x$bh where dbablk=12 and dbarfil=7;
LRU_FLAG TCH
---------- ----------
0 10
可以看到,已经是10了。但是,LRU_FLAG列仍是0。块并不会被移动到热端。
此时12号文件7号块的情况如下:热 端
冷 端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
12/7
TCH:10
除TCH变为10外,12号文件7号块并不会被移到热端。
[ 本帖最后由 晶晶小妹 于 2008-3-11 21:04 编辑 ]
-
晶晶小妹 发布于2008-03-11 21:01:53
-
步2:在另一个表以索引方式扫描若干行:
SQL> select /*+index(qsmed.zjj1) */ * from qsmed.zjj1 where id>=1750 and id<=3500;
已选择1751行。执行计划
----------------------------------------------------------
Plan hash value: 2538640105
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1772 | 164K| 31 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| ZJJ1 | 1772 | 164K| 31 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | ZJJ1_ID | 1772 | | 6 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID">=1750 AND "ID"<=3500)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
263 consistent gets
25 physical reads
0 redo size
165015 bytes sent via SQL*Net to client
1661 bytes received via SQL*Net from client
118 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1751 rows processed
这有25个物理读。为了为这25个物理读寻找可用块,服务器进程将从LRU的末端,寻找可用块,将ZJJ1相关的块的信息覆盖这些可用块。并将它们从LRU的冷端末尾,移到冷端头。
显示12号文件7号块,不会有任何变化:
SQL> select lru_flag,tch from x$bh where dbablk=12 and dbarfil=7;
LRU_FLAG TCH
---------- ----------
0 10
ZJJ1的25个物理读,目前还没有对12号文件7号块的状态有任何的影响,只不过,12号文件7号块被挤了向冷端末尾:热 端
冷 端
1
2
3
4
5
6
7
8
9
10
17
18
19
20
11
12
13
14
15
16
12/7
TCH:10
ZJJ_1
JJ_1
上图中ZJJ_1只占了4个格,这是不精确的,ZJJ_1和其索引应该占至少25个块才对,因为物理读有25个块。
[ 本帖最后由 晶晶小妹 于 2008-3-11 21:07 编辑 ]
-
晶晶小妹 发布于2008-03-11 21:02:40
-
步3:进一步加大从ZJJ_1扫描的行数:
SQL> select /*+index(qsmed.zjj1) */ * from qsmed.zjj1 where id<=7000;
已选择7000行。执行计划
----------------------------------------------------------
Plan hash value: 2538640105
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7060 | 654K| 116 (1)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| ZJJ1 | 7060 | 654K| 116 (1)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | ZJJ1_ID | 7060 | | 18 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"<=7000)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
1034 consistent gets
50 physical reads
0 redo size
668076 bytes sent via SQL*Net to client
5511 bytes received via SQL*Net from client
468 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
7000 rows processed
显示12号文件7号块,不会有任何变化:
SQL> select lru_flag,tch from x$bh where dbablk=12 and dbarfil=7;
LRU_FLAG TCH
---------- ----------
0 10
当前的状态可以近似的用如下的图表示:热 端
冷 端
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
11
12/7
TCH:10
ZJJ_1
JJ_1
步4:再加大扫描的行数:
SQL> select /*+index(qsmed.zjj1) */ * from qsmed.zjj1 where id<=17500;
已选择17500行。执行计划
----------------------------------------------------------
Plan hash value: 2538640105
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17683 | 1640K| 287 (1)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID| ZJJ1 | 17683 | 1640K| 287 (1)| 00:00:02 |
|* 2 | INDEX RANGE SCAN | ZJJ1_ID | 17683 | | 42 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"<=17500)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
2589 consistent gets
116 physical reads
0 redo size
1794670 bytes sent via SQL*Net to client
13211 bytes received via SQL*Net from client
1168 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
17500 rows processed
这一次12号文件7号块的位置和状态发生了变化,
SQL> select lru_flag,tch from x$bh where dbablk=12 and dbarfil=7;
LRU_FLAG TCH
---------- ----------
8 0
LRU_FLAG的值变为了8,TCH列被清零。这说明12号文件7号块被移到了热端。原来方格10所代表的块不再属于热端,已被挤到了冷端。热 端
冷 端
11
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
12/7
TCH:0
JJ_1
ZJJ_1
buffer cache中的LRU链+相关推荐
- Linux系统中的Page cache和Buffer cache
Free命令显示内存 首先,我们来了解下内存的使用情况: Mem:表示物理内存统计 total:表示物理内存总量(total = used + free) used:表示总计分配给缓存(包含buffe ...
- Oracle - 使用各种SQL来熟知buffer cache使用情况
这篇文章是参照甲骨论老相老师的教学视频: http://v.youku.com/v_show/id_XMzkyMjE3NTA0.html 所做的学习笔记 1. 查看某个对象所占用buffer状态: 上 ...
- buffer cache 内存管理物理结构纯干货
buffer cache 里有三种数据结构来管理内存空间 1 hash chain 2 LRU LIST 3 DIRTY LIST hash chain 是为快速定位buffer cache中块的结构 ...
- buffer cache 深度解析
本文首先详细介绍了oracle中buffer cache的概念以及所包含的内存结构.然后结合各个后台进程(包括DBWRn.CKPT.LGWR等)深入介绍了oracle对于buffer cache的管理 ...
- oracle buffer block,8 Oracle深度学习笔记——BUFFER CACHE深入一
8.Oracle深度学习笔记--BUFFER CACHE深入一 最近项目一直和ORACLE死磕,感觉总是找不到出口,只能多看书少说话了. 先记录多少是多少吧! BUFFER CACHE在ORACLE的 ...
- Oracle性能调优之--Buffer cache 的调整与优化
Oracle性能调优之--Buffer cache 的调整与优化 Buffer Cache是SGA的重要组成部分,主要用于缓存数据块,其大小也直接影响系统的性能.当Buffer Cache过小的时候, ...
- linux page buffer cache深入理解
Linux上free命令的输出. 下面是free的运行结果,一共有4行.为了方便说明,我加上了列号.这样可以把free的输出看成一个二维数组FO(Free Output).例如: FO[2][1] = ...
- ORACLE (5): buffer cache(CBC LATCH实验)
什么是cache buffers chains latch 当用户执行一条select语句的过程如下: 1.根据记录找到对应的DBA: 比如: SQL> select dbms_rowid.RO ...
- 和linux关系_Linux内核Page Cache和Buffer Cache关系及演化历史
在我们进行数据持久化,对文件内容进行落盘处理时,我们时常会使用fsync操作,该操作会将文件关联的脏页(dirty page)数据(实际文件内容及元数据信息)一同写回磁盘.这里提到的脏页(dirty ...
最新文章
- 扩增子图表解读8网络图:节点OTU或类Venn比较
- vant图标怎么显示不出来_U盘插进电脑但不显示怎么解决
- Spring注解大全(示例详解)
- java初学课程_作为java新手应该学习什么课程
- 分页设计 与 高级查询 的 结合设计
- Git异常:fatal: could not create work tree dir 'XXX': No such file or directory
- html5 粽子飘落,飘落的丁香花阅读*
- 节假日表-BaseHolidaysManager
- cmt obm odm 代工模式oem_什么是OEM,ODM与OBM
- brew mysql_brew mysql指定版本
- matlab has encountered,matlab运行程序时出现“matlab has encountered an internal problem
- 用turtle作画玩一玩吧
- ES自定义评分机制:function_score查询详解
- 使用Navicat导入.sql文件(适合新手)
- 品牌受众改造:6 个品牌如何应用网红营销
- Windows 10的最新版本是什么?
- 云宏信息科技股份有限公司
- 《Molecular Plant》新思路:比较转录组+比较基因组研究小麦高效氮利用分子机制
- SourceMap 浏览器控制台报错:DevTools failed to load SourceMap:Could not load content for ...
- Vue+nodejs开发的一个处理闲置物品的校园线上交易平台