本篇内容介绍了“数据库的性能问题有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

谓词越界常见发生在 where 谓词是时间字段的情况,总的来说统计信息记录的是一个过旧的时间,而 SQL 传入的时间是一个最新的时间范围(往往是<time time1<c<time2)由于统计信息不全,按照 CBO 计算出来的结果集就很小,在多表关联的情况下,CBO 就会选择认为的最优的关联方式,而实际执行时发现不是那么回事,有大量结果集需要扫描,就会爆发 SQL 性能问题。

谓词越界就是 select 的谓词的条件不在统计信息 low_value 和 high_value 之间,在实际选择结果集要大于 CBO 记录的结果集数量,即实际的 selectivity 偏大,这种情况下 CBO 评估出来的 selectivity 会出现严重的偏差,导致 CBO 选错执行计划。

测试验证

下面做一组测试,从执行计划 cost 看谓词越界的发生过程,先插入部分数据:

DECLAREiINT;BEGINi:=78179;WHILE(i<100000)LOOPi:=i+1;INSERTINTOtest_obj(object_id)VALUES(i);COMMIT;ENDLOOP;END;/

查看此时的 num_rows:

TEST@PROD1>selectcount(*)fromtest_obj;COUNT(*)----------94283TEST@PROD1>selectmax(object_ID),dump(max(object_id),16)fromtest_obj;MAX(OBJECT_ID)DUMP(MAX(OBJECT_ID),16)------------------------------------------------------100000Typ=2Len=2:c3,bTEST@PROD1>selectmin(object_ID),dump(min(object_id),16)fromtest_obj;MIN(OBJECT_ID)DUMP(MIN(OBJECT_ID),16)----------------------------------------------------------------------2Typ=2Len=2:c1,3--C103

不收集统计信息,此时统计列统计信息过旧,HIGH_VALUE 依然是原来的值 78179。

TEST@PROD1>selectlow_value,high_value,num_distinct,num_nullsfromDBA_TAB_COL_STATISTICSwheretable_name='TEST_OBJ'andowner='TEST';DistinctNumberLOW_VALUEHIGH_VALUEValuesNulls----------------------------------------------------------------------------------C103C308525072,462(原值)0

查询结果返回 2081 行结果集。

TEST@PROD1>selectcount(*)fromtest_objwhereobject_idbetween78200and81000;COUNT(*)----------2801计算公式为:selectivity=((VAL2-VAL1)/(HIGH_VALUE-LOW_VALUE)+2/NUM_DISTINCT)*null_adjustnull_adjust=(NUM_ROES-NUM_NULLS)/NUM_ROES计算结果为:TEST@PROD1>selectround(((81000-78200)/(100000-2)+2/94283)*(94283-0)/94283*94283)fromdual;ROUND(((81000-78200)/(100000-2)+2/94283)*(94283-0)/94283*94283)---------------------------------------------------------------2642

查看结果集发现 dictionary 值为 1,这明显是一个错误的执行计划,由于统计信息过旧,已经低于谓词条件区间(谓词过界)导致 CBO 低估了查询成本。

TEST@PROD1>selectcount(*)fromtest_objwhereobject_idbetween78200and81000;ExecutionPlan----------------------------------------------------------Planhashvalue:2217143630-------------------------------------------------------------------------------|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Time|-------------------------------------------------------------------------------|0|SELECTSTATEMENT||1|5|289(1)|00:00:04||1|SORTAGGREGATE||1|5||||*2|TABLEACCESSFULL|TEST_OBJ|1|5|289(1)|00:00:04|-------------------------------------------------------------------------------PredicateInformation(identifiedbyoperationid):---------------------------------------------------2-filter("OBJECT_ID">=78200AND"OBJECT_ID"<=81000)Statistics----------------------------------------------------------1recursivecalls0dbblockgets1117consistentgets0physicalreads0redosize423bytessentviaSQL*Nettoclient419bytesreceivedviaSQL*Netfromclient2SQL*Netroundtripsto/fromclient0sorts(memory)0sorts(disk)1rowsprocessed

重新收集统计信息再次查看执行计划。

TEST@PROD1>execdbms_stats.gather_table_stats('test','test_obj');TEST@PROD1>selectlow_value,high_value,num_distinct,num_nullsfromDBA_TAB_COL_STATISTICSwheretable_name='TEST_OBJ'andowner='TEST';DistinctNumberLOW_VALUEHIGH_VALUEValuesNulls--------------------------------------------------------------C103C30B94,2830

此时统计信息 HIGH_VALUE 已经和最初计算的值相等,Typ=2 Len=2: c3,b。再次查看执行计划,此时 CBO 已经能够产生了正确的执行计划了。

执行计划为:

TEST@PROD1>selectcount(*)fromtest_objwhereobject_idbetween78200and81000;ExecutionPlan----------------------------------------------------------Planhashvalue:2217143630-------------------------------------------------------------------------------|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Time|-------------------------------------------------------------------------------|0|SELECTSTATEMENT||1|5|314(1)|00:00:04||1|SORTAGGREGATE||1|5||||*2|TABLEACCESSFULL|TEST_OBJ|2642|13210|314(1)|00:00:04|-------------------------------------------------------------------------------PredicateInformation(identifiedbyoperationid):---------------------------------------------------2-filter("OBJECT_ID">=78200AND"OBJECT_ID"<=81000)Statistics----------------------------------------------------------0recursivecalls0dbblockgets1117consistentgets0physicalreads0redosize423bytessentviaSQL*Nettoclient419bytesreceivedviaSQL*Netfromclient2SQL*Netroundtripsto/fromclient0sorts(memory)0sorts(disk)1rowsprocessed

谓词越界主要发生在大表,按照 Oracle 统计信息收集机制,表的数据变化量达到 10% 以上才会进行统计信息收集,大表不常收集统计信息就容易爆发谓词越界。

预防方式

可对关键表实行按谓词查询条件分区,即按天或者按月分区可规避此问题发生。

“数据库的性能问题有哪些”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!