为什么Oracle分区表统计信息收集会导致全表扫描?

浅芳君_8320

浅芳君_8320

2026-10-02

350人浏览

原创

统计信息过时、granularity参数选错、直接路径读切换、全局索引未覆盖分区键是导致分区表全表扫描的四大主因,需协同排查优化。

为什么oracle分区表统计信息收集会导致全表扫描?

统计信息过时直接触发全表扫描

分区表查询走全表扫描,八成不是SQL写得差,而是优化器手里没准确的“地图”——统计信息过时或缺失。当 NUM_ROWS、AVG_ROW_LEN、DENSITY 等关键字段严重偏离真实值,CBO 会误判索引访问代价远高于全表扫描,尤其在 WHERE 条件选择性高但统计信息显示“几乎全表命中”时,它宁可扫一遍也不走索引。

典型表现:EXPLAIN PLAN 显示 TABLE ACCESS FULL,而谓词里明明有高选择性字段;DBA_TAB_STATISTICS 中 LAST_ANALYZED 时间远早于数据变更时间;分区级行数与全局行数明显对不上(比如新增百万行后 GLOBAL_STATS = 'NO')。

granularity 参数选错导致分区裁剪失效

用 DBMS_STATS.GATHER_TABLE_STATS 收集统计信息时,granularity 参数决定“谁被更新、谁被忽略”。选错就等于只修了半张地图:

  • granularity => 'PARTITION':只更新指定分区,GLOBAL_STATS 保持不变 → 查询跨多个分区时,优化器因全局统计不准,不敢裁剪,退化为全表扫描
  • granularity => 'GLOBAL':只更新全局统计,各分区统计仍是旧的 → 分区裁剪可能误判某分区为空或极小,跳过本该访问的分区,或反向扩大扫描范围
  • granularity => 'AUTO' 或 'ALL' 才能同步更新全局+所有分区统计,但代价是资源消耗大,且若未启用 INCREMENTAL 模式,每次都是全量重扫

实操建议:新增/修改分区后,优先用 granularity => 'AUTO';若表极大,改用 INCREMENTAL 模式 + granularity => 'PARTITION' 组合,避免重复扫描未变分区。

收集统计信息本身引发直接路径读(DPR)

这不是“计划错了”,而是“物理读行为变了”:统计信息收集后,Oracle 可能将原本走缓存的全表扫描,切换为 direct path read —— 绕过 Buffer Cache,直读磁盘。这在大表上反而更慢,尤其当 SQL 多次扫描同一张表(如多表 JOIN 中反复访问),db file scattered read 等待飙升。

触发条件包括:

Crypto Sniper Oracle
Crypto Sniper Oracle

机构级量化市场预言机,提供订单簿失衡(OBI)、VWAP分析、自动化报告及Telegram预警。

下载
  • 表大小超过隐含参数 _small_table_threshold(单位:数据块)
  • 表在 Buffer Cache 中的缓存占比
  • 脏块率 > 25%

注意:这个变化和执行计划无关,PLAN_HASH_VALUE 没变,但实际 I/O 路径已切换。可通过 v$session_event 查看 direct path read 等待是否突增来确认。

全局索引未覆盖分区键导致索引失效

即使统计信息最新,若查询按分区键过滤(如 WHERE part_key = 'P2024'),但全局索引建在非分区键字段(如 CREATE INDEX idx_global ON t(col_a) GLOBAL),优化器无法利用分区裁剪,索引条目分散在所有分区中,B树遍历成本不亚于全表扫描,CBO 直接弃用。

验证方法:

  • 查 DBA_PART_INDEXES 确认索引类型是否为 GLOBAL
  • 查 DBA_IND_COLUMNS 看索引列是否包含分区键
  • 执行 EXPLAIN PLAN 后,观察 Pstart/Pstop 是否为具体分区号(如 8、8),还是 KEY 或 1–MAX

修复方向:要么重建全局索引,把分区键加进索引列(需权衡 DML 性能);要么改用本地索引(LOCAL),天然支持分区裁剪。

真正棘手的是统计信息、索引结构、分区设计三者耦合——改一个参数可能暴露另一个隐藏缺陷。别只盯着 GATHER_TABLE_STATS 命令本身,先确认分区键是否入索引、INCREMENTAL 是否开启、_small_table_threshold 是否合理,再动手收集。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

oracle

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

3923

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

831

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1009

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5761

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2703

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5740

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7581

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1030

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

912

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程