如何让DBMS_STATS.GATHER_TABLE_STATS()忽略虚拟列?
如何让DBMS_STATS.GATHER_TABLE_STATS()忽略特定列?
针对你的虚拟列分析耗时问题,有几种实用方法可以控制DBMS_STATS.GATHER_TABLE_STATS()是否忽略特定列:
方法1:显式指定要分析的列(兼容所有Oracle版本)
如果你的Oracle版本较低(低于12cR2),可以通过columns参数列出所有需要分析的列,直接排除目标虚拟列。比如你的虚拟列名为HASH_COL,表为DW_TABLE,调用方式如下:
DBMS_STATS.GATHER_TABLE_STATS( ownname => '你的用户名', tabname => 'DW_TABLE', columns => 'COL1, COL2, COL3' -- 替换为除HASH_COL外的所有列名 );
这种方法的缺点是如果表中列较多,维护列名列表会比较繁琐,但胜在兼容性强。
方法2:使用EXCLUDE_COLUMNS参数(Oracle 12cR2+)
从Oracle 12c Release 2开始,DBMS_STATS.GATHER_TABLE_STATS()新增了exclude_columns参数,可以直接指定要忽略的列,用法更简洁:
DBMS_STATS.GATHER_TABLE_STATS( ownname => '你的用户名', tabname => 'DW_TABLE', exclude_columns => 'HASH_COL' -- 指定要跳过的虚拟列 );
这是最推荐的方法,无需罗列所有列,直接排除目标列即可。
方法3:临时修改列的统计属性
如果需要频繁切换是否分析该虚拟列,可以临时将列的统计属性设为NO_STATS,分析完成后再恢复:
- 先设置列不生成统计信息:
EXEC DBMS_STATS.SET_COLUMN_STATS( ownname => '你的用户名', tabname => 'DW_TABLE', colname => 'HASH_COL', no_stats => TRUE );
- 执行表分析,此时会自动跳过该列:
EXEC DBMS_STATS.GATHER_TABLE_STATS('你的用户名', 'DW_TABLE');
- 后续需要恢复分析该列时,重置属性并单独分析:
EXEC DBMS_STATS.SET_COLUMN_STATS( ownname => '你的用户名', tabname => 'DW_TABLE', colname => 'HASH_COL', no_stats => FALSE ); -- 单独分析该虚拟列 EXEC DBMS_STATS.GATHER_TABLE_STATS('你的用户名', 'DW_TABLE', columns => 'HASH_COL');
注意事项
- 无论使用哪种方法,都要确保忽略该列后不会影响查询计划的准确性——如果优化器依赖该虚拟列的统计信息来生成执行计划,就不能随意忽略。
- 数据仓库批量加载场景中,建议优先使用方法2(如果版本支持),可以大幅简化代码并提升效率。
内容的提问来源于stack exchange,提问作者Alex Bartsmon
相关产品推荐
相关产品推荐

