查不到IM_SEGMENTS视图说明In-Memory未启用:需确认inmemory_size>0、数据库OPEN状态下执行ALTER DATABASE INMEMORY、V$INMEMORY_AREA.ALLOCATED_BYTES非零。
查不到 IM_SEGMENTS 视图?先确认 In-Memory 没被禁用
oracle 12c+ 启用 in-memory 时,inmemory 参数必须为 on,且实例启动后需显式启用(不是默认开)。如果 select * from v$inmemory_area; 返回空或 bytes 为 0,说明内存池根本没分配——后面所有指标都无意义。
-
SHOW PARAMETER INMEMORY看inmemory_size是否 > 0;为 0 就别查 AWR 了 - 即使参数设了,也要确认数据库是
OPEN状态下执行过ALTER DATABASE INMEMORY;(RAC 需在所有实例执行) -
V$INMEMORY_AREA的ALLOCATED_BYTES必须非零,否则DBA_IM_SEGMENTS、V$IM_SEGMENTS全为空
V$IM_SEGMENTS 和 DBA_HIST_IM_SEGMENTS 的关键字段差异
实时视图 V$IM_SEGMENTS 只反映当前内存中加载状态;AWR 历史表 DBA_HIST_IM_SEGMENTS 是每小时快照一次(默认),字段名和含义有偏移,容易误读。
-
POPULATE_STATUS在V$视图里是COMPLETED/LOADING,但在 AWR 表里叫POPULATE_STATUS但值是数字(如 1=COMPLETED),得查V$IM_SEGMENTS的文档映射 -
BYTES_NOT_POPULATED在 AWR 表中是累计未加载字节数,不是实时差值;它不会自动清零,要结合时间范围比对 - 真正反映“查询是否走列存”的是
BYTES_IN_MEMORY/SEGMENT_SIZE比值,但注意:这个比值高 ≠ 查询命中率高——只是数据装进去了,不等于被用了
用 DBA_HIST_SQLSTAT 关联查 In-Memory 查询效果
单看列存装载量没用,得知道 SQL 实际有没有受益。Oracle 不会单独记录“这次查询用了 IM”,但会通过执行计划和统计信息暴露线索。
- 查
DBA_HIST_SQLSTAT时,重点过滤IO_CELL_OFFLOAD_ELIGIBLE_BYTES > 0且IO_INTERCONNECT_BYTES = 0——这大概率表示列存加速生效(避免了行存 I/O) - 搭配
DBA_HIST_SQL_PLAN查OTHER_XML字段,搜索"inmemory"或"storage(INMEMORY)"字符串,确认执行计划真走了列存路径 - 警惕
EXECUTIONS_DELTA和ELAPSED_TIME_DELTA的单位:AWR 默认是微秒,除以 1e6 才是秒;直接对比数值易误判性能提升
为什么 IM_SCAN_BYTES 在 AWR 报告里经常为 0?
这个指标只在启用了 INMEMORY_QUERY = ENABLE 且 SQL 显式触发列存扫描(比如带谓词的全表扫描)时才累积。很多场景下它就是不会涨。
- 普通索引访问、绑定变量未触发动态谓词、或者表上没建
INMEMORY属性,都不会计入IM_SCAN_BYTES - 它不统计列存内部压缩解压开销,只记“从 IM 区域读出的原始字节数”,所以即使列存用了,数值也可能远小于物理大小(因压缩)
- 更可靠的命中判断是组合:看
V$IM_USER_SEGMENTS.BYTES_IN_MEMORY > 0+DBA_HIST_SQLSTAT.IO_CELL_OFFLOAD_ELIGIBLE_BYTES > 0+ 执行计划含INMEMORY
列存不是开关一开就自动生效,每个对象要单独指定 INMEMORY,每个查询要满足扫描条件,每个 AWR 快照间隔里还要能捕获到真实负载——漏掉任一环,指标就失真。










