oracle 管理之道读书笔记2

1 闩锁
闩锁(Latch)的作用主要是保护数据的一致性。当很多会话用户请求同一个数据块时,要先获取闩锁才可以做动作。也就是说,当一个会话

用户要到数据库内找数据时,会先到数据库高速缓冲区中找,如果找不到表,就必须到数据文件中找。读出数据时,必须在数据库高速缓冲

区中获取足够的空闲空间,而要获取足够的空闲空间,会先去清理LRU List(把不常用的东西清出来);但要清理LRU List,必须先执行闩锁

操作,而对DB_BLOCK_ LRU_LATCHES参数的设置,表示决定使用几个闩锁。但基本上,闩锁的个数大于CPU的个数是没效益的
闩锁的个数是可以由DB_BLOCK_LRU_ATCHES参数设置的。

闩锁的最大值可以由以下两点决定:

CPU的个数×2。

DB Block Buffer/50。

以这两项中的最小的值来算。


2
DB_WRITER_PROCESSES
当数据库高速缓冲区需要读取或写回数据到数据文件中时,都需要通过DBWRn这个后台进程来协助处理,而DB_WRITER_PROCESSES主要就是设

置要由几个DBWRn来协助处理,最多可以达到10个。在此建议不要超过系统CPU的个数,如果设置的值超过了CPU的个数,那么超过的那些是

无法起作用的,

3 V$DB_CACHE_ADVICE
。当开启参数DB_CACHE_ADVICE后,经过一段时间,Oracle就会自动收集足够的相关统计数据,并预测出DB_CACHE_SIZE在不同大小情况下

的性能数据,而这些数据就是通过V$DB_CACHE_ADVICE视图来显示的,因此,可以根据这些数据对DB_CACHE_SIZE做相关的调整,以达到最佳

情况。

SELECT ADVICE_STATUS,
SIZE_FOR_ESTIMATE,
ESTD_PHYSICAL_READ_FACTOR,
ESTD_PHYSICAL_READS
FROM V$DB_CACHE_ADVICE
WHERE NAME = 'DEFAULT';
当ESTD_PHYSICAL_READ_FACTOR为1时,可以得出最好的cache分配内存。

4 V$BUFFER_POOL_STATISTICS
可以查询V$BUFFER_POOL_STATISTICS来查看每个数据库高速缓冲区的命中率,方式如下:

SQL> SELECT name,1 - (physical_reads / (db_block_gets + consistent_gets))
"HIT_RATIO" FROM sys.v$buffer_pool_statistics
WHERE db_block_gets + consistent_gets > 0;
对于SYS.V$BUFFER_POOL_STATISTICS,要先执行程序catclust.sql。

注意,原则上,获取命中率要在90%以上。

但回收率若是在90%以上,就代表这期间常用的数据是被放在回收池里的,而回收池里的数据又是经常被重复使用,所以,如果回收率是在

90%以上,就代表有问题,因为这代表90%以上的数据用完就丢了,应该将常用的数据放在保留池里。


5 共享池
共享池(Share Pool)主要是存放最近执行过的SQL语句、数据字典与PL/SQL的一些数据、表的定义和权限等,包含库缓存、数据字典高速

缓存、控制结构、可重用运行时内存等部分

1)库缓存
共享SQL区域:当执行一个SQL语句时,Oracle就会为每一句SQL打开一个游标(Cursor),并提供一个共享SQL区域和私有SQL区域空间用于

存放,当发现两个以上的会话在使用同一个SQL语句时,Oracle就会重新组织共享SQL区域,使这些会话用户能重复使用此区域的内容,从而

不浪费宝贵的资源,同时,还会在私有SQL区域里保存一份这个SQL语句的副本;反之,如果没有找到相同的SQL语句,就必须重新进行完整

的分析作业,并将分析树(Parse Tree)以及执行计划等存放在共享池内,以备下次使用。这时要注意的是,在Oracle于共享池中寻找相同的

SQL语句的过程中,如果使用的SQL语句有任何一个地方不相同,Oracle就会将此SQL语句视为在此共享池中找不到,所以需要重新进行分析

。因此,如果同一段SQL语句只是在条件的部分输入不同的值,Oracle也会认为SQL语句不同,为此,可使用绑定变量(Bind Variable),意

思是Oracle会将变动的值视为绑定变量,这样很容易在共享池里找到相同的SQL语句
当一条新的SQL语句被分析(Parse)时,Oracle从共享池中分配一块内存来存储共享SQL区域,而这块被分配的内存的大小与这条语句的复

杂性相关,如果共享池中的空间不够分配给共享SQL区域使用,Oracle就会启动LRU机制,将最近最少使用的内存块释放出来,直到有足够的

空间分配给新SQL语句的共享SQL区域;被释放出来的那块内存块内的SQL语句,如果再次被使用就必须重新分析,并重新分配共享SQL区域,

而这些动作都是比较消耗CPU的作业。这就是为何要使用绑定变量的原因了。因为如果没有使用绑定变量,当SQL语句中的变量的数值不同时

,Oracle就会将其视为一条新的语句,重复上面的分析、内存分配等动作,这都将大大消耗系统资源,降低Oracle系统性能。


2) 数据字典高速缓存
数据字典高速缓存是有关于数据库的参考信息、数据库的组织结构和数据库中的用户信息与权限等,而这些内容都是存储在表内,通常

以表和视图的形式进行呈现,就像经常使用到的V$xxx、DBA_xxx等系统的视图和表都是存储在数据字典(Data Dictionary)内。这里值得注

意的是,当SQL语句在分析的过程中时,也会去参考数据字典内的信息,而参考数据字典的动作所产生的SQL语句称为递归的SQL(Recursive

SQL),如果使用Statspack分析统计数据,此类的递归的SQL会被统计为Recursive Calls。

3)重要概念
基本上,共享池是依照修正过的LRU算法来判断其中的SQL语句与对象是否需要保留在共享池内。一般来说,当共享池需要为一个新的

SQL语句或对象分配内存时,会先确认是否有足够的空间,如果没有,就会将那些不经常使用的SQL语句和对象释放掉,也就是利用LRU机制

;但对于经常使用的SQL语句或对象,就会一直保留在共享池内。

除了LRU机制以外,当发生以下的情况时,Oracle也会将SQL语句从内存中释放出来:

当长时间没有被使用打开的游标(Open Cursor)时,SQL语句还是可能会从共享池中被释放出来,而此时如果还需要运行相关的SQL语句,

Oracle就会重新分析,并记录到共享SQL区域内。

当使用Analyze语句重新统计对象的信息时,所有与被分析对象相关的SQL语句都从共享池内被释放掉,这是因为重新分析对象,意味着原来

的执行计划可能不适用,所以必须将相关SQL语句都从共享池内释放掉,当再次使用到时,会重新分析并产生新的执行计划。

当对象的结构被修改过后,与该对象相关的所有共享SQL区域内都被注记为Invalid,当再次使用到相关的SQL语句时,就会再重新分析一次


Global Database Name被修改了,共享池内的所有信息都会被清空。

手动清空共享池的语句如下:

ALTER SYSTEM FLUSH SHARED_POOL;
当Oracle分析一个PL/SQL对象时,如过程、函数、触发器、包等,都需要从共享池中分配内存给这些对象。由于这些对象一般所占用的内存

空间都比较大,如包,因此分配的内存空间也相对较大,当Oracle经过长时间的运行后,共享池可能存在海量存储器碎片(Fragmentation)

,因而导致无法满足此类对象对于内存的需求。为了解决这类问题,Oracle专门从共享池内设置出一块共享的保留专用内存区域(Shared

Reserved Pool,简称保留区)来分配给这些具有内存需求的对象。这个保留区的默认值是共享池大小的5%,其大小一般建议是共享池的10%

,但绝对不要超过共享池大小的50%。除此之外,保留区的大小也可以通过参数SHARED_POOL_RESERVED_SIZE来调整,保留区的特点如下:

保留区是从共享池中分配,而不是直接从SGA中分配的,因此,保留区是共享池的一部分,用于存储大的对象。

在共享池中内存大于5 KB的对象就会被存放在共享池内的保留区,5 KB是默认值,而这个大小限制是可以通过隐藏参数

_SHARED_POOL_RESERVED_MIN_ ALLOC来设置的。除了在实例打开的过程中,所有小于这个数的对象永远都不会放到保留区,而大于这个值的

对象也永远不会存放到非保留区中。

当保留区有多余的内存空间时,对象也不会被放到共享池内的空间列表中,它有自己独立的保留空闭列表;相对的,当共享池空间不足时,

Oracle就利用LRU机制将不常用的对象释放,而不会影响到保留区内的对象。也就是说,保留区也是使用的LRU机制,但是在扫描时,其与共

享池是相互不影响的。

保留区内的信息可查询V$SHARED_POOL_RESERVED。关于V$SHARED_ POOL_RESERVED的详细内容,请参阅第2.3.5节。

前面提过Oracle在共享池中寻找相同的SQL语句的过程中,如果使用的SQL语句有任何一个地方不相同,Oracle就会视此SQL语句在此共享池

中找不到,所以需要重新进行分析,因此,若当同一段SQL语句只是在条件的部分输入了不同的值,Oracle也会将其视为不同的SQL语句,为

了适应这种情况,可使用绑定变量,但要如何判断SQL语句是否使用了绑定变量呢?可使用以下语句得知目前Hard Parse(硬分析)的次数与

比例,Hard Parse次数越少越好,所以比例值越接近于0越好。

select a.value as Total,b.value as "Hard Pase",
round(b.value / a.value, 2) as Ratio
from v$sysstat a, v$sysstat b
where a.name = 'parse count (total)' and b.name = 'parse count (hard)';

下面的语句查询哪些语句没使用变量绑定:
oracle 9/10:
select d.plan_hash_value plan_hash_value,
d.execntexecnt,
a.hash_valuehash_value,
a.sql_textsql_text
from v$sqltext a,
(select plan_hash_value, hash_value, execnt
from (select c.plan_hash_value,
b.hash_value,
c.execnt,
rank() over(partition by c.plan_hash_value order by
b.hash_value) as hashrank
from v$sql b,
(select count(*) as execnt, plan_hash_value
from v$sql
where plan_hash_value <> 0
group by plan_hash_value
having count(*) > 10
order by count(*) desc) c
where b.plan_hash_value = c.plan_hash_value
group by c.plan_hash_value, b.hash_value, c.execnt)
where hashrank <= 3) d
where a.hash_value = d.hash_value
order by d.execnt de SHARED_POOL_SIZEsc, a.hash_value, a.piece;


oracle 11g:
select d.plan_hash_value plan_hash_value,
d.execnt,
a.HASH_VALUE,
a.SQL_TEXT
from v$sqltext a,
(select plan_hash_value, hash_value, execnt
from (select c.plan_hash_value,
b.hash_value,
c.execnt,
rank() over(partition by c.plan_hash_value order by
b.hash_value) as hashrank
from v$sql b,
(select count(*) as execnt, plan_hash_value
from v$sql
where plan_hash_value <> 0
group by plan_hash_value
having count(*) > 10
order by count(*) desc) c
where b.plan_hash_value = c.plan_hash_value
group by c.plan_hash_value, b.hash_value, c.execnt)
where hashrank <= 3) d
where a.hash_value = d.hash_value
order by d.execnt desc, a.hash_value, a.piece;


6 共享池的重要参数
1) SHARED_POOL_SIZE
SHARED_POOL_SIZE指定了共享池的大小。在32位操作系统中,此参数的默认值是8 MB,而64位操作系统中的默认值是64 MB。

提示

Oracle 9i之前的版本和10g版本的共享池的算法是不相同的,差异如下:

Oracle 9i的算法是SHARED_POOL_SIZE的设置加上内部SGA消耗大小,因此,如果以SHOW PARAMETER SHARED_POOL_SIZE查询V$SGASTAT,并汇

总共享池的大小是不相同的。

Oracle 10g的算法是当设置了SHARED_POOL_SIZE的值,就将内部SGA消耗大小算在其中,因此,共享池真正使用的空间是SHARED_POOL_SIZE

的设置值减去内部SGA消耗大小。在10g中设置共享池的大小时必须加入这个因素,如果共享池的设置太小,在打开数据库时,将会有ORA-

0371的错误信息。

2)一般情况下,会发现保留区是很少被使用的,也就是说,5%~10%的保留区空间可能有些浪费。不过,建议经过长时间的观察再决定是否

需要调整保留区的大小。

V$SHARED_POOL_RESERVED的使用方式如下:

(1) 确认SHARED_POOL_RESERVED_SIZE的空间情况,查询语句如下:

SELECT ROUND(FREE_SPACE / 1024 / 1024, 1) "FREE SPACE MB",
REQUEST_MISSES,
REQUEST_FAILURES
FROM V$SHARED_POOL_RESERVED;

上结果的详细说明如下所示:

当REQUEST_FAILURES大于0时,增加SHARED_POOL_SIZE和SHARED_ POOL_RESERVED_SIZE的空间。

当REQUEST_MISS等于0,或是FREE_MEMORY大于等于SHARED_POOL_ RESERVED_SIZE的空间时,则增加SHARED_POOL_RESERVED_SIZE的空间。

(2) 确认SHARED_POOL_RESERVED_SIZE的命中率(Hit Ratio),查询语句如下:

SELECT (REQUEST_MISSES / (REQUESTS + 0.0001)) * 100 "REQUEST MISSES RATIO",
(REQUEST_FAILURES / (REQUESTS + 0.0001)) * 100 "REQUEST FAILURES RATIO"
FROM V$SHARED_POOL_RESERVED;

以上结果应该都要小于1%,如果大于1,应该加大SHARED_POOL_RESERVED_ SIZE


(3) V$SQL、V$SQLTEXT、V$SQLAREA与V$SQL_PLAN
V$SQL、V$SQLTEXT、V$SQLAREA与V$SQL_PLAN这4个视图都是查询在共享池中的SQL语句,而妥善的交互利用这些视图对于实例Tuning和

SQL Tuning有相当大的帮助。

V$SQL是共享池中已经分析过的SQL,其中列出了所有SQL的相关信息,但不包含GROUP BY语句,每一个SQL语句都是一笔数据,但此记录只保

留SQL语句的前1000个字符。

V$SQLAREA中记录了在共享池中分析过的每个SQL语句和准备运行的SQL语句的统计数据,和V$SQL一样只保留SQL的前1000个字符。

V$SQLTEXT视图会记录完整的SQL,但会将SQL分成不同笔的数据来存储。

V$SQL_PLAN视图包含了库缓存中所有游标所产生的执行计划,可结合V$SQLAREA获得库缓存中所有语句的查询计划。

V$SQL、V$SQLTEXT、V$SQLAREA与V$SQL_PLAN的运用如下所示:

利用V$SQL查询出使用频率最高的10句SQL:

select sql_text, executions
from (select sql_text,
executions,
rank() over(order by executions desc) exec_rank
from v$sql)
where exec_rank <= 10;
利用V$SQL查询出最耗费磁盘读的前10句SQL:
select disk_reads, sql_text
from (select sql_text,
disk_reads,
dense_rank() over(order by disk_reads desc) disk_reads_rank
from v$sql)
where disk_reads_rank <= 10;
利用V$SQL查询出最耗费内存的前10句逻辑读SQL语句:
select buffer_gets, sql_text
from (select sql_text,
buffer_gets,
dense_rank() over(order by buffer_gets desc) buffer_gets_rank
from v$sql)
where buffer_gets_rank <= 10;
利用V$SQLAREA和V$SQLTEXT查看消耗资源最多的SQL语句,步骤如下。
A SELECT hash_value, executions, buffer_gets, disk_reads, parse_calls
FROM V$SQLAREA
WHERE buffer_gets > 10000000 OR disk_reads > 1000000
ORDER BY buffer_gets + 100 * disk_reads DESC;
b 得到HASH_VALUE后,再利用V$SQLTEXT查询出实际的SQL语句。

select ADDRESS, HASH_VALUE, PIECE, SQL_TEXT
from v$sqltext
where hash_value = '2450129223'
order by PIECE;

利用V$SQLAREA查询出磁盘读次数超过100 000的查询语句,也就是最耗资源的SQL语句,语句如下:
select b.username "USER NAME",
a.disk_reads "DISK READ",
a.executions EXECUTIONS,
a.disk_reads / decode(a.executions, 0, 1, a.executions) "READ_EXEC%",
a.sql_text "SQL TEXT"
from v$sqlarea a, dba_users b
where a.parsing_user_id = b.user_id
and a.disk_reads > 100000
order by a.disk_reads desc;

利用V$SQL和V$SQL_PLAN查询出SQL语句的执行计划,步骤如下:
A 利用V$SQL查出查询的SQL语句的ADDRESS和HASH_VALUE,语句如下:

SELECT sql_text, address, hash_value FROM v$sql
WHERE sql_text like 'SELECT * FROM EMP %';
B 利用查出的ADDRESS和HASH_VALUE,配合V$SQL_PLAN相对应的字段,即可查询出此SQL语句的执行计划,语句如下;
SELECT operation, options, object_name, cost FROM v$sql_plan
WHERE address = '32557612' AND hash_value =2128902247;

利用V$SESSION的SQL_HASH_VALUE和SQL_ADDRESS字段,配合V$SQLTEXT的HASH_VALUE和ADDRESS,可查询出当前用户链接的SQL语句,步骤

如下
a 利用V$SESSION查询出SQL_HASH_VALUE和SQL_ADDRESS,语句如下
SELECT USERNAME,
TERMINAL, PROGRAM,
SQL_HASH_VALUE,
SQL_ADDRESS, TYPE
FROM V$SESSION
WHERE TYPE NOT LIKE 'BACKGROUND';

b 利用查出的SQL_HASH_VALUE和SQL_ADDRESS,再配合V$SQLTEXT相对应的字段即可,语句如下;
SELECT *
FROM V$SQLTEXT
WHERE HASH_VALUE = '889124229'
AND ADDRESS = '000000008EBE3A38'
ORDER BY PIECE;

(3) V$LIBRARYCACHE
V$LIBRARYCACHE的内容包含了关于库缓存的性能统计信息,对于共享池的性能优化有很大帮助
此表中必须特别注意PIN和GET的命中率或未命中率,当命中率小于99%或未命中率大于1%时,说明Hard Parse过多,可能需要加大共享池或是使用绑定变量等优化的动作。查询命中率的语句如下:

Select
namespace,
gets,
gethitratio*100 "GET%",
pins,
pinhitratio*100 "PIN%",
reloads,
invalidations
from
v$librarycache;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值