在 1.3 节中提到,执行计划中的 Rows 是假的,是 CBO 根据统计信息和数学公式估算出来的,所以在看执行计划的时候,一定要注意嵌套循环驱动表的 Rows 是否估算准确,同时也要注意执行计划的入口 Rows 是否算错。因为一旦嵌套循环驱动表的 Rows 估算错误,执行计划就错了。如果执行计划的入口 Rows 估算错误,那执行计划也就不用看了,后面全错。
现有如下执行计划。
select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT-------------------------------------------------------------------------------------Plan hash value: 3215660883-------------------------------------------------------------------------------------| Id |Operation |Name |Rows | Bytes | Cost(%CPU)|-------------------------------------------------------------------------------------| 0 |SELECT STATEMENT | | 78| 4212 | 15507 (1)|| 1 | HASH GROUP BY | | 78| 4212 | 15507 (1)|| 2 | NESTED LOOPS | | | | || 3 | NESTED LOOPS | | 3034| 159K| 15506 (1)||* 4 | TABLE ACCESS FULL |OPT_REF_UOM_TEMP_SDIM| 2967| 101K| 650 (14)||* 5 | INDEX RANGE SCAN |PROD_DIM_PK | 3| | 2 (0)||* 6 | TABLE ACCESS BY INDEX ROWID|PROD_DIM | 1| 19 | 5 (0)|-------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------4 - filter("UOM"."RELTV_CURR_QTY"=1)5 - access("PROD"."PROD_SKID"="UOM"."PROD_SKID")6 - filter("PROD"."BUOM_CURR_SKID" IS NOT NULL AND "PROD"."PROD_END_DATE"=TO_DATE('9999-12-31 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "PROD"."CURR_IND"='Y' AND"PROD"."BUOM_CURR_SKID"="UOM"."UOM_SKID")22 rows selected.
执行计划中 Id=4 是嵌套循环的驱动表,同时也是执行计划的入口,CBO 估算它只返回 2 967 行数据。Id=4 前面有「*」号,表示有谓词过滤4 - filter("UOM"."RELTV_CURR_QTY"=1)。
根据执行计划中 Id=4 的谓词信息,手动计算 Id=4 应该返回真正的 Rows 如下。
select count(*) from OPT_REF_UOM_TEMP_SDIM where "RELTV_CURR_QTY"=1;
COUNT(*)----------946432
手动计算出的 Rows 返回了 946 432 行数据,与执行计划中的 2 967 行相差巨大,所以本示例中,执行计划是错误的。
