Oracle执行计划(Explain Plan)显示行数错误的原因是什么?
执行计划行数估算错误的原因及解决办法
这个问题的核心原因是Oracle成本优化器(CBO)使用的表和列统计信息过时了,导致它无法准确估算查询返回的行数。
具体分析:
- 执行计划里的行数是CBO基于统计信息计算的估算值,不是实际返回行数。你在插入1200条新数据(其中200条
tip_coperta='paperback')之前,表中只有4条paperback数据,而插入后没有更新统计信息,CBO依然沿用旧的统计数据,所以估算行数还是4。 - Oracle的CBO依赖以下统计信息来估算行数:
- 表的总行数(
NUM_ROWS) - 列的不同值数量(
NUM_DISTINCT) - 列值的分布频率(
HISTOGRAM等)
这些信息没有更新的话,CBO就无法知道表数据已经发生了大幅变化。
- 表的总行数(
验证方式:
你可以查询以下视图确认统计信息是否过时:
-- 查看表的统计信息更新时间和总行数 SELECT num_rows, last_analyzed FROM user_tables WHERE table_name = 'CARTE'; -- 查看tip_coperta列的统计信息 SELECT num_distinct, num_nulls, last_analyzed FROM user_tab_col_statistics WHERE table_name = 'CARTE' AND column_name = 'TIP_COPERTA';
如果last_analyzed是你插入数据之前的时间,num_rows远小于实际的1207条(7+1200),那就说明统计信息确实没更新。
解决办法:
手动收集表的统计信息,让CBO获得准确的数据分布:
EXEC DBMS_STATS.GATHER_TABLE_STATS( ownname => '你的用户名', -- 替换为你的数据库用户名 tabname => 'CARTE', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE, -- 自动选择采样比例 cascade => true -- 同时收集索引的统计信息 );
收集完成后,再重新查看执行计划,估算的行数就会和实际情况接近了。
额外提示:
你的存储过程里每次循环都执行COMMIT,这会增加数据库的事务开销,建议改成批量提交(比如每100条提交一次),不过这和执行计划行数估算错误无关。
内容的提问来源于stack exchange,提问作者Diana
相关产品推荐
相关产品推荐

