liuziyi

liuziyi

oracle统计分析到底可以干什么?

一、问题理解与分析方向

统计信息相关的日常故障,通常不会直接表现为“统计信息报错”,而是通过执行计划变化间接表现为业务现象:某条 SQL 突然变慢、CPU 或 I/O 升高、逻辑读暴涨、连接方式从索引扫描变成全表扫描、大表被误选为 Nested Loop 等。

分析方向可以归纳为四层判断:

  1. 先确认是否属于统计信息问题:对比执行计划中的“估算行数”和实际行数;如果两者相差几个数量级,就应优先怀疑统计信息失真。同时要排除绑定变量窥探、隐式类型转换、ACS、索引被删除或新增、版本升级导致优化器行为变化等非统计信息因素。
  2. 再区分统计信息的异常类型:是“过时”“缺失”“被锁定”“采样不足”“直方图不合理”,还是“多列相关性未被描述”。不同异常的判断入口和处理边界不同。
  3. 判断影响范围:是单表、单分区、单索引,还是整个 schema 或数据库;是偶发一条 SQL,还是批量 SQL 同时劣化。
  4. 判断是否需要稳定性手段:如果统计信息本身合理但计划仍反复波动,分析方向应转向计划稳定性机制,例如 SQL 计划管理、统计信息锁定或恢复,而不是继续反复收集。

需要特别注意的是:统计信息准确不等于执行计划一定最优。日常故障中相当一部分“看起来像统计信息问题”的案例,最终根因是索引缺失、冗余索引、隐式转换或优化器特性变化。

二、建议检查的数据库对象与入口

检查对象或入口 用途 关注点
DBA_TAB_STATISTICS 表级统计信息概览 STALE_STATS 是否为 YES、LAST_ANALYZED 是否过旧、STATTYPE_LOCKED 是否被锁定、NUM_ROWS 是否与真实数据量匹配
DBA_TAB_COL_STATISTICS 列级统计与直方图概要 NDV、DENSITY、直方图桶数是否合理
DBA_TAB_HISTOGRAMS 列直方图明细 倾斜列是否被正确描述,桶数是否足够
DBA_IND_STATISTICS 索引统计信息 BLEVEL、叶子块数、聚簇因子、LAST_ANALYZED
DBA_INDEXES 索引定义与状态 执行计划引用的索引是否仍然存在、是否可用
DBA_OPTSTAT_OPERATIONS 统计信息操作历史 最近是否执行过收集、删除、锁定、恢复操作
DBA_OPTSTAT_OPERATION_TASKS 收集任务执行明细 收集任务是否失败、是否被并发或资源限制影响
DBA_SCHEDULER_JOBS 自动统计信息收集任务 任务是否存在、是否启用、上次执行时间
V$SQL / GV$SQL 游标与执行计划 SQL_ID、PLAN_HASH_VALUE、是否多个计划并存、估算行数与实际行数
AWR 相关视图与报告 历史负载与 SQL 统计 TOP SQL、执行计划历史、CPU 与 I/O 变化时间点
执行计划本身 最直接的验证入口 Rows、Cost、Cardinality、访问路径、连接方式是否与数据分布相符
10053 事件 优化器代价计算过程 基数估算、选择性计算、计划比较过程

统计信息的维护接口集中在 DBMS_STATS 包,日常分析中常见的入口包括:

  • 收集:GATHER_TABLE_STATS、GATHER_SCHEMA_STATS、GATHER_DATABASE_STATS
  • 删除:DELETE_TABLE_STATS、DELETE_SCHEMA_STATS
  • 锁定与解锁:LOCK_TABLE_STATS、UNLOCK_TABLE_STATS、LOCK_SCHEMA_STATS、LOCK_PARTITION_STATS
  • 恢复与备份:RESTORE_TABLE_STATS、EXPORT_TABLE_STATS、IMPORT_TABLE_STATS
  • 待定统计信息:PUBLISH_PENDING_STATS
  • 手工设置:SET_TABLE_STATS、SET_COLUMN_STATS
  • 系统统计:GATHER_SYSTEM_STATS

三、相关机制与背景知识

  1. 过期判定机制:Oracle 通常以对象被 DML 修改的行数是否超过总行数约 10% 作为过期判断依据,并在 DBA_TAB_STATISTICS 的 STALE_STATS 中体现。STALE_STATS 为 YES 只说明“可能不准”,不代表一定导致故障,仍需结合执行计划验证。

  2. 自动收集机制:自动统计信息收集任务在维护窗口内运行,优先处理缺失或过期的对象。任务被关闭、维护窗口过短、资源受限或对象被锁定,都会造成统计信息长期不更新。

  3. 统计信息锁定机制:锁定后 STATTYPE_LOCKED 显示为 ALL,普通 GATHER_TABLE_STATS 会报 ORA-20005;同时新建索引的统计信息也不会被自动采集,导致索引 NUM_ROWS 为空。此时可用 force 参数强制收集,或先解锁、收集后再重新锁定。

  4. 动态采样机制:当优化器发现对象缺少统计信息时,可在解析阶段做小范围采样估算。它能临时缓解“无统计信息”问题,但采样结果受级别和样本影响,不能替代正常收集;级别 0 表示关闭动态采样。

  5. 直方图机制:直方图用于描述列值倾斜分布。没有直方图时,优化器通常按 1/NDV 估算选择性;对严重倾斜列,这会产生明显偏差。但直方图桶数有上限(254),不适合的列建直方图反而可能误导优化器。

  6. 游标与计划缓存机制:统计信息更新后,已缓存的游标不一定立即失效。是否立即失效与收集时的 NO_INVALIDATE 等参数有关;否则可能出现“统计信息已更新,但仍在用旧计划”的现象。

  7. 自适应游标共享(ACS):绑定变量窥探会导致同一 SQL 生成多个子游标和多个执行计划。ACS 关闭或异常时,可能出现计划突变或固化次优计划。

  8. 计划稳定性机制:SQL 计划管理、统计信息锁定、统计信息恢复,都是在“统计信息本身可能变化”的前提下保持计划稳定的手段。它们与“重新收集统计信息”解决的是不同层面的问题。

  9. 版本差异:19c 引入实时统计信息,在 DML 过程中维护基础统计,降低过时统计信息的影响,但不能取代自动收集任务;升级后优化器新特性也可能改变既有执行计划。

四、可能关联的故障模式

故障模式 核心含义 常见触发条件
过时统计信息导致次优执行计划 优化器基于旧统计估算基数与代价,选择高成本计划 大量插入、删除、更新后未及时收集
统计信息不准确导致执行计划错误 统计信息过时、缺失或采样不准,导致基数估算错误 自动采样比例过低、直方图桶数不足、大量 DML 后未更新
统计信息缺失导致新 SQL 执行计划劣化引发 CPU 飙升 新 SQL 上线时对象无统计信息,优化器误判选择性 新表、新分区、刚导入数据、统计信息被删除
有列统计信息无表统计信息导致 CBO 失效 表级统计缺失但列级存在,优化器基数估算基础不完整 收集不完整、对象状态异常、手工设置统计信息不配套
统计信息锁定导致收集失败或索引统计缺失 锁定后收集报 ORA-20005,新索引统计不被采集 为稳定计划锁定统计信息后长期未解锁
统计信息锁定导致执行计划错误 锁定保留了已经失真的旧统计信息 数据量大幅变化但统计信息被锁定
统计信息陈旧导致错误执行计划 数据分布变化后优化器仍按旧分布选择路径 分区表新增分区、历史数据归档、批量迁移
库缓存中游标因统计信息过时而性能不佳 缓存游标仍使用旧统计信息生成的计划 统计信息已更新但游标未失效,或未重新解析
执行计划突变(统计信息相关) 计划从索引扫描变为全表扫描等,响应时间突增 统计信息变化、索引变化、优化器特性变化、ACS 异常

五、可参考的案例或经验

案例 关键现象与证据 可借鉴点
Oracle RAC CPU 使用率过高:统计信息缺失导致 SQL 执行计划走错 RAC 双机 CPU 持续超过 90%,AWR 定位到单条 TOP SQL,执行计划历史显示异常变化,最终发现自动统计信息收集任务被关闭、表统计信息过旧 自动收集任务被关闭是容易被忽视的根因;需同时检查任务状态与执行计划历史
Oracle 19c RAC PDB 统计信息锁定导致查询走错索引 SQL 已走索引但仍慢,逻辑读约 80 万次;STALE_STATS=YES 且 STATTYPE_LOCKED=ALL,收集时报 ORA-20005;重新收集后 NUM_ROWS 从 148 万增至 6742 万,计划改为更合适的索引 “走了索引”不代表计划正确;锁定状态与 NUM_ROWS 严重偏差是关键证据
统计信息缺失导致新 SQL 执行计划劣化引发 CPU 飙升 新上线 SQL 在目标表上因统计信息过期或缺失,优化器误选低选择性列索引,产生大量逻辑读,AAS 升至 95 新 SQL 上线前应确认相关对象统计信息是否新鲜
CPU 使用率过高故障案例:冗余索引与缺失统计信息导致执行计划错误 AWR 定位到 COUNT 查询,绑定变量执行快、常量执行超过 1 小时;执行计划引用已不存在的索引,表上存在多个冗余索引且统计信息过时 统计信息问题常与索引变更、冗余索引同时出现,不能只看统计信息
Oracle 19c ACS 关闭引发执行计划突变案例 核心 SQL 在固定时间点突然变慢,执行计划突变并固化为次优计划,最终通过清除游标并恢复 ACS 解决 并非所有计划突变都是统计信息导致,需排查 ACS 与游标
某 HIS 系统业务卡顿与统计信息收集阻塞案例 业务高峰与统计信息收集窗口重叠,收集任务对业务造成资源争用 收集统计信息本身也可能成为故障源,需关注收集窗口与资源消耗

日常经验可以总结为几点判断原则:

  • 先看执行计划,再看统计信息:不要仅凭 STALE_STATS=YES 就下结论,要用估算行数与实际行数的偏差来验证。
  • 先确认对象是否被锁定:很多“收集了但没变化”的问题,根因是 STATTYPE_LOCKED。
  • 区分“统计信息问题”和“计划稳定性问题”:前者通过收集解决,后者可能需要锁定、恢复或计划管理。
  • 保留回退手段:重要表在重新收集或调整前备份统计信息,出现异常计划时可恢复。
  • 关注收集任务本身:自动任务被关闭、窗口过短、资源争用,都是日常统计信息故障的常见源头。

posted on 2026-11-04 17:48  刘子毅  阅读(12)  评论(0)    收藏  举报

导航