About me:Oracle ACE pro,optimistic,passionate and harmonious. Focus on ORACLE,MySQL and other database programming,peformance tuning,db design, j2ee,Linux/AIX,Architecture tech,etc
全部博文(172)
分类: Oracle
2020-06-17 09:00:55
进一步分析:
ORACLE内部计算选择性都是以数字格式计算,因此,遇到字符串类型,会将字符串转换成RAW类型,再将RAW类型转换成数字,并且ROUND到左起15位,这样对于转换后的数字很大,可能原来字符串相差比较大的,内部转换后的数字比较接近,这样就会引起选择性计算不准确问题。如下例:
执行计划如下:
NUM_ROWS:139495263
NUM_DISTINCT:139495263
LOW_VALUE:3838383630303830313239383031363230383620
HIGH_VALUE:4E554C4C35303839302020202020202020202020
NUM_NULLS:0
SQL SIM_NO谓词最大最小值内部一样
SQL> select get_internal_value('89860005126436720074') from dual;
GET_INTERNAL_VALUE('89860005126436720074')
----------------------------------------------------------------------------------------------------------
291929174972906000000000000000000000
SQL> select get_internal_value('8986005126436720050') from dual;
GET_INTERNAL_VALUE('8986005126436720050')
----------------------------------------------------------------------------------------------------------
291929174972906000000000000000000000
sel:1/139495263+1/139495263+(291929174972906000000000000000000000-291929174972906000000000000000000000)/(high_value-low_value)
=1/139495263+1/139495263
card:=139495263*(1/139495263+1/139495263)=2
而实际根据条件查询出的行数 29737305。因此,索引走错了。
解决方法:
收集TEM_ID列直方图,由于内部算法有一定限制,导致值不同的字符串,内部计算值可能一致,所以收集直方图后,针对字符串值不同,但是转换成数字后相同的,ORACLE会将实际值存储到ENDPOINT_ACTUAL_VALUE中,用于校验,提高执行计划的准确性。走正确索引GPYTM_ID后,运行时间从1小时以上到5s内。
执行计划如下所示: