性能测试调优方案知识汇总.docx
- 文档编号:23932126
- 上传时间:2023-05-22
- 格式:DOCX
- 页数:52
- 大小:254.08KB
性能测试调优方案知识汇总.docx
《性能测试调优方案知识汇总.docx》由会员分享,可在线阅读,更多相关《性能测试调优方案知识汇总.docx(52页珍藏版)》请在冰豆网上搜索。
性能测试调优方案知识汇总
-、数据库实例优化
1.oracle_SharedPool优化和LibraryCacheLatch冲突优化
简介
本文档旨在介绍从Oracle7到Oracle11gsharedpool调优的关键问题。
特别对于存在下列问题的系统非常重要:
«librarycachelatch/es或者latch:
librarycache之类的Latch争用
«sharedpoollatch或者latch:
sharedpool之类的Latch争用
・高CPU解析时间
«V$LIBRARYCACHE中的高reloads
«多版本的cursors
«大量的parsecall
«经常发生ORA-04031错误
TroubleshootingSteps
什么是sharedpoo?
Oracle在SGA的一个特定区域中保留SQL语句,packages,对象信息以及其它一些内容,这就是大家熟悉的sharedpool。
这个共享内存区域是由一个复杂的cache和heapmanager构成的。
它需要解决三个基本问题:
1.每次分配的内存大小是不一致的,从几个字节到上千个字节;
2.因为sharedpool的目的是为了最大化共享信息,所以不是每次一个用户用完之后就可
以释放这段内存(在传统的heapmanager方式会遇到这个问题)。
内存中的信息可能
对于其他session来说是有用的Oracle并不能事先知道这些内容是否会被再次用到;
3.Sharedpool中的内容不能被写入到硬盘区域中,这一点和传统cache是不一样的。
只有
H可重建的信息可以被覆盖,因为他们可以在下次需要时重建。
基于这些背景,我们就可以理解sharedpool的管理是一件非常复杂的事情。
下面的章节列
出了一些影响sharedpool性能和它相关的latch的关键问题,包括:
专用术语
LiteralSQL
一个LiteralSQL语句是指在predicate中使用具体值,而不是使用绑定变量,即不同的执行语句使用的具体值可能是不一样的。
例1:
应用程序使用了:
SELECT*FROMempWHEREename='CLARK:
而不是:
SELECT*FROMempWHEREename=:
bind1;
例2:
以下语句不用绑定变量但是也不会被认为是literalSQL,因为这个语句可以被多次执
行共享。
SELECTsysdateFROMdual;
例3:
如果整个应用都是用相同的值20'来检查’version'的话,那么这个语句可以被认为是可
以共享的。
SELECTversionFROMapp_versionWHEREversion>2.0;
HardParse(硬解析)
如果一个新的SQL被发起,但是又不在sharedpool里面的话,它将被完整的解析一次。
例如:
Oracle必须在sharedpool中分配内存,检查句法和语义等等这被称为hardparse,
它在CPU使用和latch获取上的都是非常消耗资源的。
SoftParse(软解析)
如果一个session发起一个已经在sharedpool中的SQL语句并且它可以使用一个当前存在的版本,那么这个过程被称为一个'softparsed对于应用来说,它只需请求解析这个语句。
完全相同的语句?
如果两个SQL语句的含义相同但是没有使用相同的字符,那么Oracle认为它们是不同的语
句。
比如SCOTT在一个Session中提交的这两个语句:
SELECTENAMEfromEMP;
SELECTenamefromemp;
尽管它们实际上是相同的,但是因为大写字母?
E和小写字母’e'的区别,他们不会被认为是
完全相同的语句。
SharableSQL
如果是两个不同的session发起了完全相同的SQL语句,这也不意味着这个语句是可以共享的。
比如说:
用户SCOTT下有一个表EMP,发起了下面的语句:
SELECTENAMEfromEMP;
用户FRED有一个自己的表也叫EMP并且发起相同的语句:
SELECTENAMEfromEMP;
尽管语句完全一样但是由于需要访问的EMP表是不同的对象,所以需要对这条语句产生不同的版本。
有很多条件来判断两个完全一致的SQL文本是不是真的是完全相同(以至于他
们可以被共享),包括:
・语句中引用的所有的对象名必须都被解析成实际相同的对象
*发起语句的session中的optimizer相关的参数应该一致
*绑定变量的类型和长度应该是”相似的”
(这里不做详细讨论,但是类型和长度的不同确实会导致语句被分为不同的版本)
*发起语句的NLS(NationalLanguageSupport)设置必须相同
语句的版本
正如之前在'SharableSQL冲描述的,如果两个语句字面上完全相同但是又不能被共享,则会
对相同的语句产生不同的’version',即版本。
如果Oracle要匹配一个包含多个版本的语句,它将不得不检查每一个版本来看它们是不是和当前被解析的语句完全相同。
所以最好用以下
方法来避免高版本数(highversioncount):
*客户端使用的绑定变量最大长度需标准化
•如果有大量的schema会包含相同名字的对象,那么避免使用一个相同的SQL语句。
比女口:
SELECTxxFROMMYTABLE;并且每个用户都有一个自己的MYTABLE的情况
•在Oracle8.1可以将_SQLEXEC_PROGRESSION_COST设置成'0'
LibraryCache和SharedPoollatches
sharedpoollatch是用来保护从sharedpool中分配和释放内存的关键性操作。
Librarycachelatche(以及Oracle7.1中的librarycachepinlatch)是用来保护librarycache中的操作。
所有的这些Latch都是潜在的资源争用的对象,latchgets发生的次数直接受到sharedpool
中活动(activity)个数的影响,特别是parse操作。
任何减少latchgets或者sharedpool中活动(activity)个数的尝试都有助于提高性能和可扩展性。
LiteralSQL和SharedSQL的比较
这一个小章节中描述了literalSQL和sharableSQL各自的优点:
LiteralSQL
在有完整的统计信息并且SQL语句在predicate(限定条件)中使用具体值时,基于成本的
优化器(CBO)能工作的最好。
比较下面的语句:
SELECTdistinctcust_refFROMordersWHEREtotal_cost<10000.0;
和
SELECTdistinctcust_refFROMordersWHEREtotal_cost<:
bindA;
对于第一个语句,CBO可以使用已经收集的histogram来判断是否使用全表扫描比使用
TOTAL_COST列上索引扫描快(假设有索引的话)。
第二个语句CBO并不知道绑定变量":
bindA"对应行数的比例,因为该绑定变量没有一个具体的值以确定执行计划。
例:
":
bindA"
可以是0.0或者99999999999999999.9。
Orders表上两个不同的执行路径的响应时间可能会不同,所以当你需要CBO为你选出最好
的执行计划的时候,选用使用literal语句会更好。
在一个典型的DecisionSupportSystems(决策支持系统)中,重复执行标准'语句的时候非常少,所以共享一个语句的几率很小,而且
花在Parse上的CPU时间只占每个语句执行时间的非常小一部分,所以更重要的是给optimizer尽可能详细的信息,而不是缩短解析时间。
SharableSQL
如果应用使用了literal(无共享)SQL,则会严重限制可扩展性和生产能力。
在对CPU的需
求、librarycache和sharedpoollatch的获取和释放次数方面,新SQL语句的parse成本很高。
比如:
仅仅parse一个简单的语句就可能需要获取和释放librarycachelatch20或者30次。
除非它是一个临时的或者不常用的SQL,并且需要让CBO得到尽可能多的信息来生成一个
好的执行计划,否则最好让所有的SQL是共享的。
减轻SharedPool负载
Parse一次并执行多次
在OLTP类型的应用中,最好的方法是只让一个语句被解析一次,然后保持这个cursor的打
开状态,在需要的时候重复执行它。
这样做的结果是每个语句只被Parse了一次(不管是softparse还是hardparse)。
显然,总会有些语句很少被执行,所以作为一个打开的cursor维护
它们是一种浪费。
请注意一个session最多只能使用参数:
open_cursors定义的cursor数,保持cursor打开会增力口总体opencursors的数量。
OCI中开发者能直接控制cursor,在预编译器中,HOLD_CURSOR参数控制cursor是否被保持打开。
消除LiteralSQL
如果你有一个现有的应用程序,你可能没法消除所有的literalSQL,但是你还是得设法消除
其中一部分会产生问题的语句。
从V$SQLAREA视图可能找到适合转为使用绑定变量的语
句。
下面的查询列出SGA中有大量相似语句的SQL:
SELECTsubstr(sql_text,1,40)"SQL",
count(*),
sum(executions)"TotExecs"
FROMv$sqlarea
WHEREexecutions<5
GROUPBYsubstr(sql_text,1,40)
HAVINGcount(*)>30
ORDERBY2
J
在10g以上的版本可以用下面的语句:
SETpages10000
SETlinesize250
columnFORCE_MATCHING_SIGNATUREformat99999999999999999999999
WITHcAS
(SELECTFORCE_MATCHING_SIGNATURE,
COUNT(*)ent
FROMv$sqlarea
WHEREFORCE_MATCHING_SIGNATURE!
=0
GROUPBYFORCE_MATCHING_SIGNATURE
HAVINGCOUNT(*)>20
)
sqAS
(SELECTsql_text,
FORCE_MATCHING_SIGNATURE,
row_number()over(partitionBYFORCE_MATCHING_SIGNATUREORDERBYsql」d
DESC)p
FROMv$sqlareas
WHEREFORCE_MATCHING_SIGNATUREIN
(SELECTFORCE_MATCHING_SIGNATURE
FROMc
)
)
SELECTsq.sql_text,
sq.FORCE_MATCHING_SIGNATURE,
t"unsharedcount"
FROMc,
sq
WHEREsq.FORCE_MATCHING_SIGNATURE=c.FORCE_MATCHING_SIGNATURE
ANDsq.p=1
ORDERBYtDESC
对SQL语句,去掉重复的空格(不包括字符常量),将大小写转换成相同,比如均为大写
(不包括字符常量)后,如果SQL相同,那么SQL语句的exact_matching_signature就是相
同的。
对SQL语句,去掉重复的空格(不包括字符常量),将大小写转换成相同,比如均为大写(不包括字符常量),然后去掉SQL中的常量,如果SQL相同,那么SQL语句的
force_matching_signature就是相同的。
但是例外的情况是:
如果SQL中有绑定变量,
force_matching_signature就会与exact_matching_signature—样的生成标准。
可以看到,现在exact_matching_signature与force_matching_signature完全一样了。
从force_matching_signature的特性,我们可以想到一个用途,用于查找没有使用绑定变量的SQL语句,类似于使用plan_hash_value来查找。
注意:
如果系统中有librarycachelatch争用的问题,上面的语句会导致争用加剧。
值40,5和30只是示例,这个查询查找前40个字符相同的,只被执行过很少次数,而又至
少在sharedpool里出现30次的语句。
通常来说,literal语句以下面的形式开始,并且每个语句的前面部分字符是相同的:
"SELECTcol1,col2,col3FROMtableWHERE..."
注意:
在转化literalSQL使用绑定变量时有一定程度的限制。
请放心我们已经反复证明转化
那些经常执行的语句会消除sharedpool的问题并且能显著提高可扩展性。
请查看你的应用中使用的工具的文档来决定如何在语句中使用绑定变量。
避免Invalidations
有些命令会将cursor的状态变成成INVALIDATE。
这些命令直接修改cursor相关对象的上下文环境。
它包括TRUNCATE,表或索弓I上的ANALYZE或DBMS_STATS.GATHER_XXX关联对象的权限变更。
相对应的cursor会留在SQLAREA中,但是下次被引用时会被完全
reload并重新parse,所以会对数据库的整体性能造成影响。
下面的查询可以帮我们找到Invalidation较多的cursor:
SELECTSUBSTR(sql_text,1,40)"SQL",
invalidations
FROMv$sqlarea
ORDERBYinvalidationsDESC;
更多的详细信息,请参考Note:
115656.1和Note:
123214.1
CURSOR_SHARING参数(8.1.6以上)
(在Oracle8.1.6引入).
这个参数需要小心使用。
如果它被设为FORCE,那么Oracle会尽可能用系统产生的绑定变量来替换原来SQL中的literals部分。
对于很多仅仅是literal不一样的相似的语句,这会让它们共享cursor。
这个参数可以在系统级别或者session级别动态设置:
ALTERSESSIONSETcursor_sharing=FORCE;
或者
ALTERSYSTEMSETcursor_sharing=FORCE;
或者在init.ora中设置
注意:
因为FORCE会导致系统产生的绑定变量替换literal,优化器(CBO)可能会选择一个不
同的执行计划,因为能够产生最好执行计划的literaI值已经不存在了。
在Oracle9i(以上),可以设置CURSOR_SHARING=SIMILAR。
如果这些语句只是literal
部分不同,并且这些literal不会对SQL的含义有影响,或者可能会导致使用不同的执行计划,那么SIMILAR会共享这些语句。
此增强功能适用于当FORCE会产生一个不同并且不
是想要的执行计划时,从而提高了参数CURSOR_SHARING的可用性。
设置
CURSOR_SHARING=SIMILAR,Oracle会决定哪些literals可以被"安全"的替换成绑定变量,这样做的结果是有些SQL在可能产生更好执行计划的时候也不会被共享。
关于这个参数的更多详细信息,请参考Note:
94036.1。
注意:
Similar在Oracle12中不推荐使用。
(译者注:
根据Note:
1169017.1,Oracle12将会移
除cursor_sharing=SIMILAR的设置,而且在11g中就已经不推荐使用了,因为有
AdaptiveCursorSharing的新特性)请参考:
Document:
1169017.1ANNOUNCEMENT:
Deprecatingthecursor_sharing=SIMILARsetting
SESSION_CACHED_CURSORS参数
是一个可以在instanee级别或者session级别设置的数值参数:
ALTERSESSIONSETsession_cached_cursors=NNN;
数值NNN决定在一个session中可以被'cached'的cursor的个数。
当一个语句被parse的时候,Oracle会首先检查session的私有缓存中指向的语句,如果有可
被共享的语句版本的话,它就可以被使用。
这为经常被parse的语句提供了一个捷径,可以
比soft或者hardparse使用更少的CPU和非常少的Latchget。
为了被缓冲在session缓存中,同样的语句必须在相同的cursor中被parse3次,之后一个指向sharedcursor的指针会被添加到你的session缓存中。
如果session缓存cursor已达上限,则最近最少使用的那一个会被替换掉。
如果你还没有设置这个参数,建议先设置为50作为初始值。
之后查看bstat/estat报告的统计信息章节的'sessioncursorcachehits的值,从这个值可以判断cursor缓存是否有作用。
如果
有必要的话,可以增加或者减少cursor缓存的值。
SESSION_CACHED_CURSORS对于forms经常被打开和关闭的OracleForms应用非常有用。
CURSOR_SPACE_FOR_TIME参数
控制同一个语句不同执行之间一个cursor是否部分被保持(pin)住。
如果设置其他参数都
没效果的话,就值得尝试这个参数。
这个参数在有不经常被使用的共享语句,或者有非常多
的cursor被pinning/unpinning的时候是有帮助的。
(查看视图:
v$latch_misses-如果大多数latch等待是因为cursor的pinning和unpinning导致的"kglpnc:
child"和"kglupc:
child").
你必须保证sharedpool对于工作负载来说是足够大的,否则性能会受到严重影响而且最终会产生ORA-4O31错误。
如果你把这个参数设为TRUE,请留意:
•如果SHARED_POOL对于工作负载来说太小的话更容易产生ORA-4031错误。
・如果你的应用有cursor泄漏,那么泄漏的cursor会浪费大量内存并在一段时间的运行之后对性能产生负面影响。
•目前已知的设置为true可能会导致的问题:
•
・Bug:
770924(Fixed8061and8160)ORA-600[17302]mayoccur
・Bug:
897615(Fixed8061and8160)GarbageExplainPlanoverDBLINK
・Bug:
1279398(Fixed8162and8170)ORA-600[17182]fromALTERSESSIONSETNLS…
CLOSE_CACHED_OPEN_CURSORS参数
这个参数已经在Oracle8i被废弃。
控制当一个事务提交时是否PL/SQLcursor被关闭。
默认值是FALSE,该设置在不同commits之后保持PL/SQLcursor打开以减少hardparse的次数。
如果设成TRUE的话可能会增加SQL在不用的时候被从sharedpool中清除出去的可能性。
SHARED_POOL_RESERVED_SIZE参数
已经有相当多的文档解释过参数。
这个参数在Oracle7.1.5被引进,它把sharedpool的一
部分预留出来用于较大内存的分配。
这个预留区域是从sharedpool自身划分出来的。
从实践角度来说我们应该把SHARED_POOL_RESERVED_SIZE设成
SHARED_POOL_SIZE的10%,除非sharedpool非常大或者SHARED_POOL_RESERVED_MIN_ALLOC被设得小于默认值:
*如果sharedpool非常大的话,设成10%会浪费很多内存因为可能设成几MB就够用了。
•如果SHARED_POOL_RESERVED_MIN_ALLOC被设的较小,则很多的空间请求都会符合从保留空间中分配的条件,那么10%也许就不够了。
查看视图的FREE_SPACE列可以很容易监控保留区域的使用情况。
SHARED_POOL_RESERVED_MIN_ALLOC参数
在Oracle8i这个参数是隐藏的.
尽管有些情况下SHARED_POOL_RESERVED_MIN_ALLOC设成4100或者4200可能对缓解较大压力下的sharedpool的冲突有帮助,但是在大多数情况下应保持默认值。
SHARED_POOL_SIZE参数
控制sharedpool自己的大小,它能对性能造成影响。
如果太小,则共享的信息会被从共享池中交换出去,过一阵子有需要被重新装载(重建)。
如果literalSQL使用较多而且sharedpool又很大,长时间使用后内部内存freelist上会产生大量小的内存碎片,使得sharedpool
latch被持有的时间变长,进而导致性能问题。
在这种情况下,较小的sharedpool也许比较
大的sharedpool好。
因为Bug:
986149的改进,这个问题在8.0.6和8.1.6以上版本被大大减少了。
.
注意:
一定要避免由于sharedpool设置过大进而导致的swap的发生的情况,因为当swap发生的时候性能会急剧下降。
参考Note:
1012046.6来根据工作量计算SHARED_POOL_SIZE需要的大小。
_SQLEXEC_PROGRESSION_COSTparameter参数(8.1.5以上)
这是一个Oracle8.1.5引入的隐含参数。
这里提到它是因为默认设置可能导致SQL共享方面
的一些问题。
设置成0会避免在sharedpool中产生语句高版本的问题。
例:
在init.ora文件中增加这个参数
#_SQLEXEC_PROGRESSION_COST并且设成0来避免SQL共享问题#参考
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 性能 测试 方案 知识 汇总
![提示](https://static.bdocx.com/images/bang_tan.gif)