天天看点

调优4(buffer cache 调整)

第四章、 buffer cache 调整

1、buffer cache 功能

buffer cache: 用于存放从datafile 里读出的数据块的镜像,并共享这些数据块,采用LRU算法

buffer cache 数据块状态:

pending:数据块正在使用,状态未决

dirty: 被修改过的块,还未写入到datafile

free:

已经从cache里写入到datafile的块,可以被覆盖

LRU LIST :链接从datafile里读出的块的头部信息,一般用于free 状态的块

Checkpoint list (Dirty

list):链接dirty block ,等待dbwr 写入到datafile

db_cache_size 指定默认池大小,一般数据块都放在默认池中,默认池管理采用LRU

db_keep_cache_size :指定keep

池的大小,用于存放经常访问的小的对象的数据块。(比如索引块(常驻cache))

db_recycle_cache_size: 指定recycle

池的大小,用于存放偶尔访问对象的数据(比如偶尔做全表扫描的表的数据块)

2、设置buffer cache 的大小

对于sga 动态管理:

Granule 是内存分配的最小unit

Granule =4m sga<1g

Granule =16m sga>1g

----通过v$buffer_pool查看buffer cache

select NAME,BLOCK_SIZE,RESIZE_STATE,CURRENT_SIZE,BUFFERS from

v$buffer_pool

NAME BLOCK_SIZE RESIZE_STA

CURRENT_SIZE BUFFERS

--------------------------------------------------

---------- ---------- ------------ ----------

DEFAULT

8192 STATIC 156 19461

16384 STATIC 12

756

通过oracle advisory 调整buffer cache 的大小

15:01:33 SYS@ test1>show parameter db_cache

NAME TYPE

VALUE

------------------------------------ -----------

------------------------------

db_cache_advice string

ON

---默认oracle 会通过顾问来产生一个建议的大小

Buffer Pool Advisory DB/Inst: TEST1/test1 End Snap: 12

-> Only rows

with estimated physical reads >0 are displayed

-> ordered by Pool,

Block Size, Buffers For Estimate

Est

Phys Estimated Est

Size for Size Buffers

Read Phys Reads Est Phys % dbtime

P Est (M) Factr (thousands)

Factr (thousands) Read Time for Rds

--- -------- ----- ------------

------ -------------- ------------ --------

D 16 .1 2

1.4 6 28 32.9

D 32 .2 4

1.1 5 22 25.9

D 48 .3 6

1.1 5 21 24.7

D 64 .4 8

1.0 5 20 23.5

D 80 .5 10

D 96 .6 12

D 112 .7 14

D 128 .8 16

D 144 .9 18

D 160 1.0 20

D 164 1.0 20

size for est: buffer cache 期望的大小

size factr: 期望尺寸和实际尺寸的比率

buffers:

缓存的个数(数据块),以千为单位

est phys read factr:产生物理读得因子

从以上可以看出,buffer cache 在64m 是比较合适的,在16m ,产生物理读得可能性增加了40%

15:05:05 SYS@ test1>SELECT

size_for_estimate,buffers_for_estimate,estd_physical_read_factor,estd_physical_reads

FROM

V$DB_CACHE_ADVICE WHERE name = ‘DEFAULT‘ AND block_size = (SELECT value FROM

V$PARAMETER WHERE name = ‘db_block_size‘)AND advice_status = ‘ON‘;

SIZE_FOR_ESTIMATE BUFFERS_FOR_ESTIMATE ESTD_PHYSICAL_READ_FACTOR

ESTD_PHYSICAL_READS

----------------- --------------------

------------------------- -------------------

12 1497

2.1167 9421

24 2994

1.2083 5378

36

4491 1.0028 4463

48

5988 1 4451 ;当前比较合适的尺寸

60

7485 1 4451

72 8982 1 4451

84 10479 1 4451

96 11976 1

4451

108 13473 1

120 14970 1

132 16467

1 4451

144 17964

156 19461

168

20958 1 4451

180

22455 1 4451

192

23952 1 4451

204 25449 1 4451

216 26946

228 28443

240

29940 1 4451

20 rows selected.

3、buffer cache 调优目标

在oltp的库中,server 进程可以在buffer cache

找到所需要的块,提高块的命中率

1)通过oracle 顾问设置一个合适的尺寸,并提高块的命中率

2)设置不同的cache :default 、keep 、recycle

3)将表缓存到cache

4)对于排序和并行读,跳过buffer cache

-------buffer cache 命中率

physical reads:物理读,直接从磁盘读取数据块到buffer cache

physical reads direct:

物理直接读,从磁盘读取数据块到pga ,跳过sga(一般比如用于排序操作)

physical reads direct (lob):

对大对象的直接读

session logical reads:会话读取的所有数据块次数,包括物理读和一致性读等

13:56:17 SYS@ test1>SELECT ROUND(1 - ((physical.value - direct.value -

lobs.value) / logical.value),3) *100||‘%‘

13:56:19 2 "Buffer Cache Hit

Ratio"

13:56:27 3 FROM v$sysstat physical,

13:56:38 4 v$sysstat

direct,

13:56:47 5 v$sysstat lobs,

13:56:54 6 v$sysstat

logical

13:57:02 7 WHERE physical.name = ‘physical reads‘

13:57:13 8

AND direct.name = ‘physical reads direct‘

13:57:22 9 AND lobs.name =

‘physical reads direct (lob)‘

13:57:32 10 AND logical.name = ‘session

logical reads‘;

Buffer Cache Hit

Ratio

-----------------------------------------

99.5%

Elapsed: 00:00:00.04

13:57:41 SYS@ test1>

--对于OLTP的库,应该稳定在95% 以上。

4、通过建立不同的cache ,合理的使用buffer cache 空间,提高buffer cache的命中率

15:34:31 SYS@

test1>alter system set db_keep_cache_size=12m;

System altered.

Elapsed: 00:00:00.18

15:34:39 SYS@ test1>alter system set

db_recycle_cache_size=12m;

Elapsed: 00:00:00.09

15:34:53 SYS@ test1>show parameter cache

db_cache_size big integer 32M

db_keep_cache_size

big integer 12M

db_recycle_cache_size big

integer 12M

object_cache_max_size_percent integer

10

object_cache_optimal_size integer

102400

session_cached_cursors integer 20

案例:

使用keep 和recycle 池

---默认所有对象的块都会放入到default cache

15:37:24 SCOTT@ test1>select segment_name,segment_type,bytes/1024

,buffer_pool from user_segments

15:37:34 2 where segment_name in

(‘EMP‘,‘PK_EMP‘);

SEGMENT_NAME SEGMENT_TYPE BYTES/1024

BUFFER_

------------------------------ ------------------ ----------

-------

EMP TABLE 64

PK_EMP INDEX 64

Elapsed: 00:00:00.16

15:37:38 SCOTT@ test1>

----把经常调用的小的对象的块放入到keep (比如索引)

15:39:08 SCOTT@ test1>alter index pk_emp storage (buffer_pool keep);

Index altered.

Elapsed: 00:00:00.21

----对于偶然做全表扫描的表的数据块可以放入到recycle

15:39:34 SCOTT@ test1>alter table emp storage(buffer_pool recycle);

Table altered.

Elapsed: 00:00:00.07

15:40:06 SCOTT@ test1>select

segment_name,segment_type,bytes/1024 ,buffer_pool from user_segments

15:40:16

2 where segment_name in (‘EMP‘,‘PK_EMP‘);

RECYCLE

PK_EMP INDEX 64 KEEP

Elapsed: 00:00:00.03

15:40:23 SCOTT@ test1>

15:50:01 SCOTT@ test1>select ename,sal,deptno from emp where

deptno=10;

ENAME SAL DEPTNO

---------- ---------- ----------

CLARK

2450 10

KING 5000 10

MILLER

1300 10

----查看用户会话读取的数据块情况

15:49:19 SYS@ test1>select

s.username,io.block_gets,io.consistent_gets,io.physical_reads

15:49:33 2

from v$sess_io io,v$session s

15:49:37 3 where io.sid=s.sid and

s.username is not null;

USERNAME BLOCK_GETS CONSISTENT_GETS

PHYSICAL_READS

------------------------------ ---------- ---------------

--------------

SYS 9 899

61

SYS 0 16

1

Elapsed: 00:00:00.01

15:49:48 SYS@ test1>/

SCOTT 0 99

Elapsed: 00:00:00.02

block_gets :在做dml 操作时读取的数据块

consistent_gets: SELECT

时读取的数据块

physical_reads :物理读

---KEEP 和 rcycle 池使用

14:20:27 SCOTT@ test1>alter index pk_emp storage(buffer_pool keep);

15:03:39 SCOTT@ test1>alter table emp storage(buffer_pool recycle);

14:36:09 SCOTT@ test1>select * from emp;

14:36:26 SYS@ test1>/

SCOTT 0 39

SYS 171 8717

549

14:40:07 SCOTT@ test1>update emp set sal=sal+1000 where deptno=20;

5 rows updated.

-----当update

操作时,由于emp表的块都放在recycle池中,select查询完成,这些数据块被消除;所以此次update操作,产生了物理读。

14:36:32

SYS@ test1>/

SCOTT 6 2999

94

Elapsed: 00:00:00.00

14:40:22 SCOTT@ test1>select * from emp1;

14:40:25 SYS@ test1>/

SCOTT 6 3069

101

14:41:16 SCOTT@ test1>update emp1 set sal=sal+1000 where deptno=20;

8 rows updated.

------emp表数据块在default 池,所以这些数据块被共享在buffer cache 里,在做update

时候,不会产生物理读。

14:41:22 SYS@ test1>/

SCOTT 14 3082

14:41:46 SYS@ test1>

15:07:51 SCOTT@

test1>analyze table emp estimate statistics;

Table analyzed.

Elapsed: 00:00:00.44

15:11:34 SCOTT@ test1>select * from emp where

ename=‘SCOTT‘;

EMPNO ENAME JOB MGR HIREDATE SAL COMM

DEPTNO

---------- ---------- --------- ---------- --------- ----------

---------- ----------

7788 SCOTT ANALYST 7566 19-APR-87

9000 20

Execution

Plan

----------------------------------------------------------

Plan hash

value: 3220259315

---------------------------------------------------------------------------------------------

|

Id | Operation | Name | Rows | Bytes | Cost (%CPU)|

Time

0 | SELECT STATEMENT | | 1 | 32 | 2 (0)|

00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 |

32 | 2 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN |

EMP_ENAME_IND | 1 | | 1 (0)| 00:00:01

Predicate Information (identified by operation

id):

---------------------------------------------------

2 - access("ENAME"=‘SCOTT‘)

Statistics

recursive calls

0 db block gets

3 consistent

gets

0 physical reads

0 redo size

828

bytes sent via SQL*Net to client

384 bytes received via SQL*Net from

client

2 SQL*Net roundtrips to/from client

0 sorts

(memory)

0 sorts (disk)

1 rows processed

15:11:43 SCOTT@ test1>

15:10:46 SYS@ test1>select

name,PHYSICAL_READS,DB_BLOCK_GETS,CONSISTENT_GETS from

v$buffer_pool_statistics;

NAME PHYSICAL_READS DB_BLOCK_GETS

CONSISTENT_GETS

-------------------- -------------- -------------

---------------

KEEP 2 0

6

RECYCLE 5 0

20

DEFAULT 4401 4271

85050

DEFAULT 0 0 0

5、关于buffer cache的等待事件

测试案例:

15:06:01 SCOTT@ test1>alter session enable parallel dml;

Session altered.

15:06:04 SCOTT@ test1> begin

15:06:18 2

for i in 1..500000 loop

15:06:18 3 execute immediate ‘insert /*+

parallel (4) */ into t1 values (‘||i||‘)‘;

15:06:18 4 end

loop;

15:06:18 5 end;

15:06:18 6 /

16:00:20 SYS@ test1>select event ,total_waits from

v$system_event

16:00:39 2 where event in (‘free buffer waits‘,‘buffer

busy waits‘);

EVENT

TOTAL_WAITS

----------------------------------------------------------------

-----------

buffer busy waits

16:01:06 SYS@ test1>

1 select name ,PARAMETER1,PARAMETER2 ,PARAMETER3 from v$event_name

2*

where name like ‘buffer busy%‘

NAME PARAMETER1 PARAMETER2

PARAMETER3

-------------------- -------------------- --------------------

--------------------

buffer busy waits file# block#

class#

buffer busy group# obj#

block#

------通过:

PARAMETER1: 处于等待事件中块所在的file#

PARAMETER2: 处于等待事件中块所在的

这样就可以通过两个参数来判断,这些块的类型(段头块、data 块、索引块、undo 块)

free buffer waits: server 进程从datafile 读取block 到buffer cache时,一般因为在buffer

cache没有空闲的buffer

解决: 增加buffer cache大小,或者让dbwr 写脏块释放空间

buffer busy

waits: 一般多个server 进程同时访问一个块

1)段头部:在做insert 时,因为free list 列表而引起的等待

解决:1)增加free list

2)将段空间管理采用自动方式(位图)

2)普通数据块:多个进程访问一个块

解决: 1)用小的块

2)增大pctfree

3)如果是索引块,索引是通过序列生成的主键,采用反向索引

3)undo 块:

多个server进程同时访问undo

解决: 1)对事务采用分批提交

2)增加rollback段或采用undo 表空间

---查询busy block 数据块类型及段

16:00:20 SYS@ test1> select ‘Segment Header‘

class, a.segment_type, a.segment_name, a.partition_name from dba_segments a,

v$session_wait b

where a.header_file = b.p1 and a.header_block = b.p2 and

b.event = ‘buffer busy waits‘

union

select ‘Freelist Groups‘ class,

a.segment_type, a.segment_name, a.partition_name from dba_segments a,

where b.p2 between a.header_block + 1 and (a.header_block +

a.freelist_groups) and a.header_file = b.p1 and a.freelist_groups > 1 and

select a.segment_type || ‘ block‘

class, a.segment_type, a.segment_name, a.partition_name from dba_extents a,

where b.p2 between a.block_id and a.block_id + a.blocks - 1

and a.file_id = b.p1 and b.event = ‘buffer busy waits‘

and not exists

(select 1 from dba_segments where header_file = b.p1 and header_block =

b.p2);

buffer busy waits:

#!/bin/bash

export ORACLE_SID=test1

count=0

while [ $count -lt 1000 ]

do

sqlplus ‘sys/oracle as sysdba‘<<EOF

update tb1 set object_id=1000 ;

rollback;

EOF

count=`expr $count + 1`

done

[oracle@rh6 ~]$ cat 4.sh

update tb1 set object_name=‘aaa‘ ;

[oracle@rh6 ~]$

13:35:30 SYS@ test1 > select

size_for_estimate,SIZE_FACTOR,buffers_for_estimate,estd_physical_read_factor,estd_physical_reads

13:36:11

2 FROM V$DB_CACHE_ADVICE WHERE name = ‘DEFAULT‘ AND block_size = (SELECT

value FROM V$PARAMETER WHERE name = ‘db_block_size‘)AND advice_status =

‘ON‘;

SIZE_FOR_ESTIMATE SIZE_FACTOR BUFFERS_FOR_ESTIMATE ESTD_PHYSICAL_READ_FACTOR

----------------- ----------- --------------------

4 .25

496 1.0955 71824

8 .5 992 1.0481

68718

12 .75 1488

1.0229 67070

16 1 1984

1 65565

20 1.25

2480 .9727 63772

24 1.5 2976 .9531

62492

28 1.75 3472

.9377 61483

32 2 3968

.9187 60235

8 rows selected.

13:36:12 SYS@ test1 >/

496 1.0963 79584

8 .5 992 1.05

76223

1.0239 74327

1 72591

2480 .9719 70552

24 1.5 2976 .9508

69023

.9335 67764

.9129 66267

13:36:49 SYS@ test1 >select event ,total_waits

from v$system_event

13:37:04 2 where event in (‘free buffer waits‘,‘buffer

free buffer waits

3623

4

13:37:10 SYS@ test1 >show parameter cache

client_result_cache_lag big

integer 3000

client_result_cache_size big integer

db_16k_cache_size big integer 12M

db_2k_cache_size

big integer 0

db_32k_cache_size big

integer 0

db_4k_cache_size big integer

db_8k_cache_size big integer 0

db_cache_advice

string ON

db_cache_size big

integer 16M

db_flash_cache_file

string

db_flash_cache_size big integer

db_keep_cache_size big integer

16M

db_recycle_cache_size big integer

result_cache_max_result integer

5

result_cache_max_size big integer 768K