CBO优化器的基本概念:
可传递性:
1、简单谓词传递
t1.c1=t2.c1 and t1.c1=10,Oracle会自动将t2.c1=10的条件添加。
2、连接谓词传递
t1.c1=t2.c1 and t2.c1=t3.c1,Oracle会自动将t1.c1=t3.c1的条件添加。
3、外连接谓词传递
t1.c1=t2.c1(+) and t1.c1=10,Oracle会自动将t2.c1(+)=10的条件添加。
CBO的局限性:
1、CBO会默认目标SQL语句where条件中出现的各个列之间是独立的,没有关联关系。
2、CBO会假设所有的目标SQL都是单独执行的,并且互不干扰。
不考虑SQL执行已经缓存到Buffer Cache,下次执行不需要访问物理IO到磁盘读索引叶子块、数据块等,高估用索引的成本。
3、CBO对直方图统计信息有诸多限制。
Oracle 12c之前,Frequency类型的直方图对应的Bucket数量不能超过254,如果目标列的distinct值的数量超过254,Oracle就会使用Height Balanced类型的直方图。对于Height Balanced类型的直方图,因为Oracle不会记录所有的nopopular value的值,所以CBO选错执行计划的概率会比Frequency类型的情形高。
如果针对文本类型的字段收集直方图统计信息,则Oracle只会将该文本类型字段的文本值头32个字节取出来(实际只取头15个字节),并将其转换成一个浮点数,然后将这个浮点数作为上述文本型字段的直方图统计信息存储于数据字典中。对于那些超过32个字节的文本型字段,只要对应记录的文本值的头32个字节相同,Oracle收集直方图统计信息时,就会认为这些记录文本值相同,但实际是不同的。进而选择错误的执行计划。
4、CBO在解析多表关联的目标SQL时,可能会漏选正确的执行计划。
SQL各表之间可能的连接顺序总数是n!,10个表连接三百多万,15个表连接一百多亿。
CBO至多只会考虑其中根据_OPTIMIZER_MAX_PERMUTATIONS计算出来的有限种可能。
只要目标SQL正确的执行计划不在上述有限可能之中,则CBO一定会漏选正确的执行计划。
SELECT i.ksppinm name, CV.ksppstvl VALUE, CV.ksppstdf isdefault,
DECODE (BITAND (CV.ksppstvf, 7), 1, 'MODIFIED', 4, 'SYSTEM_MOD', 'FALSE') ismodified,
DECODE (BITAND (CV.ksppstvf, 2), 2, 'TRUE', 'FALSE') isadjusted FROM sys.x$ksppi i, sys.x$ksppcv CV
WHERE i.inst_id = USERENV ('Instance') AND CV.inst_id = USERENV ('Instance') AND i.indx = CV.indx
AND i.ksppinm LIKE '%_optimizer_max_%'
AND i.ksppinm LIKE '/_%' ESCAPE '/' ORDER BY REPLACE (i.ksppinm, '_', '');
NAME
---------------
_optimizer_max_permutations
DESCRIPTION
---------------
optimizer
maximum join permutations per query block
VALUE
ISDEFAULT ISMODIFIED ISADJ
---------------
--------- ---------- -----
2000
TRUE FALSE FALSE