設為首頁收藏本站

艾歐踢論壇

 找回密碼
 立即註冊

QQ登錄

只需一步,快速開始

搜索
熱搜: 活動 交友 discuz
查看: 560|回復: 0
打印 上一主題 下一主題

In Memory—Oracle 12C重要新特性IMO详解

[複製鏈接]
跳轉到指定樓層
樓主
發表於 2018-4-24 10:54:50 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
IMO,即In-Memory Option。为Oracle 12c中最为重要的新特性之一。12.1开始支持该新特性。

目录

  • 基本介绍
  • 可以启用In-Memory列存储功能的级别
  • 适合使用IMO功能的操作类型
  • 可以使用INMEMORY子句的命令
  • 查询数据库中哪些segment启用了IM
  • 不适合使用IM的操作
  • 数据压缩
  • IM的存储设置
  • 与IMO相关的初始化参数
  • 在表,表空间,或者物化视图上启用IM
  • 与IM相关的等待事件
  • 与IM相关的统计信息


一.基本介绍

In-Memory列存储组件,为12c 中SGA的可选组件。可以用来存储表、表分区、以及其他数据库对象的副本。启用该选项,我们可以在SGA中按列存储某些对象,而不是原来的按行存储。
ps:看到按列存储,会有人想到Sybase的IQ数据库咩?

In-Memory列存储是SGA中的一个新的静态池(static pool)。所谓静态,也就是说里面的对象需要我们dba手工管理。在该池中,数据都是按列存储,而原来sga的db buffer cache中,数据依然还是按行存储。这样,整个内存,就可以同时提供数据的按行和按列存储。要启用该选项,INMEMORY_SIZE参数,需要设置为非零值。当然,不能小于100M,否则,你会碰到如下错误:


二. 可以启用In-Memory列存储功能的级别

  • Column
  • Table
  • Materialized view
  • Tablespace
  • Partition


如果在表空间级别上启用该功能,则所有存储在该表空间中的表和物化视图都将继承这一功能。

三. 适合使用IMO功能的操作类型

  • A query that scans a large number of rows and applies filters that use operators such as the following: =, <, >, and IN
  • A query that selects a small number of columns from a table or materialized view with a large number of columns, such as a query that selects five columns from a table with 100 columns 查询一个多列对象中的少数几列
  • A query that joins a small table to a large table
  • A query that aggregates data


需要注意的一个点:一般情况下,复合索引可以用来提升某些分析或者报表查询的性能。但是,当数据为按列存储时,这些索引,基本就不需要了。

四. 可以使用INMEMORY子句的命令

  • CREATE TABLE
  • ALTER TABLE
  • CREATE TABLESPACE
  • ALTER TABLESPACE
  • CREATE MATERIALIZED VIEW
  • ALTER MATERIALIZED VIEW


五. 查询数据库中哪些segment启用了IM

想查询当前数据库中哪些segment启用了IM,可以执行如下查询语句:

SELECT OWNER, SEGMENT_NAME, INMEMORY_PRIORITY, INMEMORY_COMPRESSION
FROM V$IM_SEGMENTS;

例如:



注意这个查询的后两列:

INMEMORY_PRIORITY,优先级设置,如果没有设置则为none。

INMEMORY_COMPRESSION 压缩级别,也就是说,可以压缩存储。

需要注意的是,数据库对象即便启用了IM,该对象也不一定就会放到内存中。所以,执行该查询,可能无法查到你想要的结果。比如:


--查询结果当中木有啊,那把这张表在IM中的优先级设置一下看看。
--注:关于优先级,我们后面再说。


--恩,还是木有。是优先级太低了?


在对表tab_test启用IM时,即便设置了最高的优先级,也还是查询不到。
在这里稍微推测一下,应该跟表的数据量相关。

六. 不适合使用IM的操作

  • Queries with complex predicates
  • Queries that select a large number of columns
  • Queries that return a large number of rows
  • Queries with multiple large table joins


另外,如果对象的所有者为sys,或者是存储在SYSTEM 或SYSAUX表空间中的,则无法使用IM选项。

七. 数据压缩

在IM列存储选项中,可以将数据压缩,然后缓存到内存中。压缩选项如下:


IM操作,可以分别针对DML、query以及capacity等数据缓存用途进行不同级别的压缩,压缩级别越高,可存储的对象也就越多,但是性能就会下降。

来看个例子:


可以看到压缩效果。
注:这两个测试表都是通过CTAS方式以dba_objects中的数据创建。

八. IM的存储设置

IM占用的是SGA的空间,由参数inmemory_size手动控制。

但是该参数为上限设置,如果要启用IM选项的对象大小加起来超过了该参数的值,那怎么办?

当我们对多个对象启用IM时,我们可以让oracle自己来处理,看看空间不够的时候,oracle会把哪些对象移出IM。

另外一种方法,则是在给对象启用IM时设置优先级。

IM中可以设置的优先级如下:


表格中的优先级从低到高,优先级越高,往IM里面存放的时候,就越优先考虑。实质上,算是对要缓存对象的优先级排序,以便oracle在IM空间不足的时候,知道如何处理对象。

当数据库重启时,所有优先级为非none的对象,都将在数据库启动过程中缓存到IM中。

需要注意的是:

1,优先级只能应用于表或者表的分区级别,而无法应用到列级别上。

2,如果对象小于64K,则该对象不会存放到IM中。前面的tab_test就是如此。

来看实验:

数据库版本12.1.0.2,os版本rhel6.4,本IM系列文章均是如此。


ok,那么,如果启用IM的表,数据量发生了变化,那IM能自己探测么?

往下看:


但是我又查了下统计信息收集,user_tables里面反倒木有更新:


注意蓝色的内容,行数和统计信息收集时间都没有发生变,但是IM中的却都变化了。

另外,我又测试了下tab_obj3,将其优先级从high降至low,然后也是立马就被丢出IM了········


稍微总结一下:
1.即便设置了表的inmemory选项,也必须要在访问表中数据之后,才会被缓存到IM中。
2.已经缓存在IM中的表,如果降低其优先级,将会被从IM中移除(实际上,只要优先级发生改变,则该表就会被移除。这一点,各位可以自行测试确认)。
3.IM会自动感知存放在IM中的表的数据变化,但是原有以行模式存储的数据的统计信息,则不会自动更新。

继续做实验:


也就是说,如果给表启用了IM,即便这张表没有被存入到IM中,其执行计划显示也会是TABLE ACCESS INMEMORY FULL。

当然,实际的执行计划显然不会是这个。这一点,我们需要注意。

九. 与IMO相关的初始化参数

INMEMORY_SIZE:IM使用的内存空间大小,默认为0。如果非零,则不得小于100M。但是在多租户环境下,单个pdb的IM size,便不受CDB中该参数大小的制约,如果你手工设置某一个或者某几个PDB的IM size的话。如果不单独设置,则各个pdb直接继承CDB中该参数的设置。

INMEMORY_FORCE:是否启用IM,如果为default,则启用;为off,不启用。

INMEMORY_CLAUSE_DEFAULT:该参数指定了默认的IM子句的内容。如果为空,也就是其默认值,等同于no inmemory。但是如果指定了非空值,则会改变IM的默认设置。

例如:
alter system set
INMEMORY_CLAUSE_DEFAULT='INMEMORY MEMCOMPRESS FOR CAPACITY HIGH'
scope=spfile;

然后重启数据库,选择一张表,启用IM:

alter table tab_test inmemory;

则等同于:

alter table tab_test inmemory memcompress for capacity high;

关于该参数,更详细的内容,可参考:

https://docs.oracle.com/database/121/REFRN/GUID-5772F775-2A3E-4BC8-AA03-B8FF383BEE52.htm#REFRN10350

INMEMORY_QUERY:指定是否启用IM查询。将其设置为enable,则启用;disable,则不启用。

INMEMORY_MAX_POPULATE_SERVERS:该参数指定了处理IM数据的最大后台进程个数。依赖于系统的cpu内核数目,有点类似于并行进程相关的参数设置。

INMEMORY_TRICKLE_REPOPULATE_SERVERS_PERCENT: 该参数用于控制IM中对象数据的重新载入的进程数,该值为INMEMORY_MAX_POPULATE_SERVERS参数的百分比。

OPTIMIZER_INMEMORY_AWARE:用于控制CBO是否使用IM选项,为false,则忽略;为true,则考虑。

十. 在表,表空间,或者物化视图上启用IM

要在表,表空间,或者物化视图上启用IM功能,你需要先在数据库级别启用IM选项,也就是说,你要满足如下条件:

1.数据库版本在12.1.0或者以上。
2.inmenory_size设置为100M或者以上。
3.重启数据库
4.查看下当前im可以使用的内存大小:
show parameter inmemory_size。
当然,这一步可选。

与表相关的IM的几个例子:

1.在创建表时直接启用IM:
CREATE TABLE test_inmem (
     id        NUMBER(5) PRIMARY KEY,
     test_col  VARCHAR2(15))
  INMEMORY;

2.创建表完成之后,使用alter命令启用IM:
ALTER TABLE oe.product_information INMEMORY;

3.启用IM并设置压缩级别:
ALTER TABLE oe.product_information INMEMORY
            MEMCOMPRESS FOR CAPACITY LOW;

4.启用IM并设置优先级:
ALTER TABLE oe.product_information INMEMORY PRIORITY HIGH;

5.启用IM并同时设置压缩级别和优先级:
ALTER TABLE oe.product_information INMEMORY
  MEMCOMPRESS FOR CAPACITY HIGH
  PRIORITY LOW;

6.对表中部分列组合启用IM,并设置压缩级别:


注:可以查看v$im_column_level视图来了解列的压缩级别。

7.关闭IM:

ALTER TABLE oe.product_information NO INMEMORY;
再注:对于列,无法设置单独的优先级,只能对表,或者表分区设置。

又注:可以通过查看v$im_segments来了解哪些对象已经被缓存到了IM中。

与表空间相关的几个IM的例子:

1.在创建表空间时启用IM:

CREATE TABLESPACE tbs1
DATAFILE 'tbs1.dbf' SIZE 40M
ONLINE
DEFAULT INMEMORY;

注:因为我们没有指定该表空间的压缩级别及优先级,所以其默认值为MEMCOMPRESS FOR QUERY, 以及 PRIORITY NONE。

2.使用alter命令修改表空间的IM选项设置:

ALTER TABLESPACE tbs1 DEFAULT INMEMORY
MEMCOMPRESS FOR CAPACITY HIGH
PRIORITY LOW;

与物化视图相关的IM的几个例子:

1.创建物化视图时启用IM:

CREATE MATERIALIZED VIEW oe.prod_info_mv INMEMORY
AS SELECT * FROM oe.product_information;  

注:此时的压缩级别及优先级设置,与上面表空间的默认设置一样。

2.创建后修改IM设置:

ALTER MATERIALIZED VIEW oe.prod_info_mv INMEMORY PRIORITY HIGH;

Data Pump中的im应用:

在impdp对象的时候,可以指定如下选项

TRANSFORM=INMEMORY:y 保留导出对象的IM设置
TRANSFORM=INMEMORY:n 不保留导出对象的IM设置
TRANSFORM=INMEMORY_CLAUSE:string 在导入时重新设置导出时的IM设置

当然,你也可以在EM中使用IM,详情可参见:

https://docs.oracle.com/database/121/ADMIN/memory.htm#ADMIN14309

12c中,与IM相关的数据字典表,我特意去查了下官方文档,无论是cdb,dba,all还是user打头的,基本都没有相关的内容。于是我搜了下v$开头的视图,查询结果如下:


这其中,V$IM_COLUMN_LEVEL和V$IM_SEGMENTS两个在前面已经涉及到过。我们这里统一把这些视图说一下:

V$INMEMORY_AREA:启用IM的对象所占用的内存空间。查询该视图,你就会知道,IM用于存储对象的内存区域,分为两个部分,一个以1M为分配单位,用于存储列数据,另外一个以64K为分配单位,用于存储对象的元数据(metadata)和事务日志(transaction journal)。

来看例子:


V$IM_COLUMN_LEVEL:用于记录列的压缩级别。

V$IM_COL_CU:记录IMCU中基于列的统计信息。

V$IM_HEADER:记录IM区对象所分配IMCU的详细信息。

V$IM_SEGMENTS:记录存储在IM中的段的属性。

V$IM_SEGMENTS_DETAIL:记录存储在IM中的段的详细属性(至于详细到什么程度,各位去对比这两个视图的列名即可。

V$IM_SEG_EXT_MAP:记录IM区对象的所有区间映射关系。

V$IM_SMU_CHUNK:记录IM中对象的元数据的块信息。

V$IM_SMU_HEAD:记录IM中对象的元数据的头信息。

V$IM_TBS_EXT_MAP:记录IM区1M子池对象的区间映射关系。

V$IM_USER_SEGMENTS:记录当前用户下IM段对象的存储属性。

*IMCU 是In Memory Compression Units

是数据在内存中分配的块的大小,比较类似于数据库中extent的概念。后台进程ora_w00*在装载数据时,会分配自己的IMCU,并将分配给该进程的数据加载到该IMCU中。此后,当访问IM区中的列数据时,我们在统计信息中看到的consistent gets值也就是统计所访问IMCU的个数和所需访问metadata块的个数之和。特定对象所分配IMCU的详细信息,可从视图V_$IM_HEADER中查询。而其metadata块的信息可从视图V_$IM_SMU_CHUNK和V_$IM_SMU_HEAD查询。

在In Memory内部,以IMCU为单位,Oracle维护了一个In Memory Storage Index,记录IMCU单元中该列的最大值,最小值。此外,Oracle也会在metadata区为每个IMCU建立相应的metadata dictionary, metadata信息中会有一些列的统计信息。视图V_$IM_COL_CU可以帮助查询这些metadata dictionary信息。

十一.与IM相关的等待事件


十二. 与IM相关的统计信息



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 轉播轉播 分享分享 分享淘帖
回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

小黑屋|Archiver|手機版|艾歐踢創新工坊    

GMT+8, 2024-5-29 10:26 , Processed in 0.280434 second(s), 18 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表