快速确认热点块需查gv$segment_statistics中'gc buffer busy'前10对象,若集中于某小表或索引即为热点块;否则查sql逻辑读与私网延迟。
直接看 gv$segment_statistics 里 'gc buffer busy' 排名前 10 的对象,如果集中在某张小表或某个索引上,基本就是热点块问题;否则得查 sql 逻辑读和私网延迟,别等 awr。
怎么快速确认是不是热点块
AWR 报告里的 Segments by Global Cache Buffer Busy 是滞后指标,问题正在发生时它还没生成。必须用实时视图定位:
- 跑这句查当前最热的段:
SELECT owner, object_name, subobject_name, object_type, value FROM (SELECT owner, object_name, subobject_name, object_type, value FROM gv$segment_statistics WHERE statistic_name = 'gc buffer busy' ORDER BY value DESC) WHERE ROWNUM - 如果
object_name高度集中(比如全是config_param或idx_order_status),且value差距大(前 3 名占总量 80%+),基本锁定是热点块 - 如果结果分散、数值接近,就不是块争用,要转向查
gv$session的logical_reads_per_sec和私网 ping 延迟(ping -s interconnect_ip 500)
Hash 分区到底能不能拆热点块
能,但只对“查询条件固定 + 键值分布相对均匀”的场景有效。比如订单状态查 status_code IN ('P','S'),而所有 'P' 都落在同一分区块上——这就是典型适用场景。
- 分区列必须是实际 SQL 中用于过滤的列,不能是无关字段
- 键值不能严重倾斜:若 95% 的记录都是
'P',Hash 后仍会扎堆在少数几个 bucket,反而加剧争用 - 新建表建议从
PARTITIONS 8起步;已有表改分区必须用DBMS_REDEFINITION,ALTER TABLE ... SPLIT PARTITION不支持非分区转分区 - 分区后务必执行:
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA','TABLE_NAME',GRANULARITY=>'ALL');,否则 CBO 可能选错执行计划
为什么 gc buffer busy acquire 和 gc buffer busy release 同时高企
这两个事件同时飙升,尤其是 gc buffer busy release 占比超 30%,说明问题不在数据块本身,而在远程实例的协调能力或网络传输环节。
- 先查:
SELECT inst_id, event, total_waits, time_waited_micro FROM gv$system_event WHERE event IN ('gc buffer busy acquire','gc buffer busy release') ORDER BY time_waited_micro DESC; - 再查阻塞源头:
SELECT * FROM gv$ges_blocking_enqueue WHERE blocker_inst_id IS NOT NULL; - 最后验证私网:用
oifcfg getif确认私网接口,然后ping -s测 500B/8KB 包延迟;超过 1ms 就要怀疑网卡驱动、巨帧或交换机配置 - 注意:
_gc_policy_time和gc_files_to_locks这类参数调高通常无效,它们不解决 buffer pin 冲突,只影响 GCS 调度频率
容易被忽略的细节
分区后没配会话亲和(session affinity)或没建本地索引,GC 等待可能不降反升;反向索引只缓解索引叶块争用,对表块完全无效;Range 分区对 create_time > SYSDATE-7 这类查询才真正有用,Hash 在这种场景下等于白做。











