适用对象:
Oracle 数据库 – 12.1.0.2
作者:
Mahesh Reddy M
简介:
随着 Oracle Database 12c In-Memory 的引入,单个数据库现在可以高效地支持混合工作负载,既为事务提供最佳性能,又同时支持实时分析和报告。In-Memory 使数据集市和数据仓库均可提供更多的临时分析,从而使最终用户现在能够同时运行多个业务驱动查询,并且只需花费以前运行一个查询的时长。使用此功能,您可以采用纵列格式(而不是典型的行格式)将列、表、分区和实例化视图存储在内存中。In-Memory 列存储(IM 列存储)是 12.1.0.2 修补程序集的标题功能。
Oracle Database 12c In-Memory 架构:
传统上,数据仅以行格式存储,然而,In-Memory 数据库仅采用纵列格式存储数据。因此,oracle database 12c 支持双格式架构。
- 只要请求数据进行读/写操作(数据操作),它们就会被加载到传统行存储区(缓冲区缓存)
- 只要为只读操作请求数据,它们就被会填充到新的 In-Memory 列存储中。当然,此填充包括从行到纵列格式的转换。
- 每当提交包括插入、更新或删除的事务时,新数据将立即同时显示在行存储和 in-memory 列存储中。因此,两个存储在事务上是一致的
In-Memory 列存储:
Database In-Memory 使用 In-Memory 列存储,这是被称为 In-Memory Area 的 System Global Area (SGA) 的新组件。IM 列存储中的数据不会以传统行格式保存,而是使用新的列格式。IM 列存储不会替换缓冲区缓存,而是充当补充,因此现在可以用行和列格式将数据存储在内存中
In-Memory area 是 SGA 内的静态池,其大小由初始化参数 INMEMORY_SIZE(默认值为 0)控制。In-Memory area 的当前大小在 V$SGA 中可见
IM 列存储被进一步划分为两个池:
- 1 MB 池 — 存储实际的列格式化数据
- 64k 池 — 存储对象的元数据。
通过下面的查询,我们可以查看每个池中可用的内存量
SQL> select * from v$inmemory_area;
POOL |
ALLOC_BYTES |
USED_BYTES |
POPULATE_STATUS |
CON_I |
1MB POOL |
2.5767E+11 |
2.3569E+11 |
完成 |
1 |
64KB POOL |
6.4408E+10 |
876347392 |
完成 |
1 |
1MB POOL |
2.5767E+11 |
2.3569E+11 |
完成 |
2 |
64KB POOL |
6.4408E+10 |
876347392 |
完成 |
2 |
1MB POOL |
2.5767E+11 |
2.3569E+11 |
完成 |
3 |
64KB POOL |
6.4408E+10 |
876347392 |
完成 |
3 |
表 1: 每个池中的可用内存
启用 IM 列存储:
作为静态池,在重新启动数据库实例之前,对 INMEMORY_SIZE 参数所做的任何更改都不会生效。它也不会受到自动内存管理 (AMM) 的影响或控制。In-Memory area 的最小大小必须为 100MB。
sql> ALTER SYSTEM SET SGA_TARGET=500G SCOPE=SPFILE;
sql> ALTER SYSTEM SET INMEMORY_SIZE=300G SCOPE=SPFILE;
sql>SHUTDOWN IMMEDIATE;
sql>STARTUP;
ORACLE 实例开始。
总 System Global Area:4.2950E+11 个字节
固定大小:7677400 个字节
可变大小:2.0938E+10 个字节
数据库缓冲区:8.5899 E + 10 个字节
重做缓冲区:529190912 个字节
In-Memory Area:3.2212 E + 11 个字节
数据库已装载。
数据库已打开。
可使用下面的查询查看 In-Memory 设置
SQL> SHOW PARAMETER INMEMORY
NAME TYPE VALUE
---------------------------------- ----------- -----
inmemory_clause_default string
inmemory_force string DEFAULT
inmemory_max_populate_servers integer 1
inmemory_query string ENABLE
inmemory_size biginteger 300G
inmemory_trickle_repopulate_servers_ integer 1
百分数
optimizer_inmemory_aware boolean TRUE
我们还可以在 CDB 和 PDB 级别设置 inmemory_size 参数。如果您在 PDB 级别设置此参数,则无需重新启动实例或 PDB。所有 PDB 值的总和小于或等于 CDB 值。
我们可以在下面所示的 PDB 级别启用和禁用 In-Memory 选项
连接到 PDB,然后执行下面的命令
禁用:
Alter system set inmemory_size=0; 或
Alter system reset inmemory_size;
启用:
Alter system set inmemory_size=20G;
In-Memory 优先级级别:
IM 列存储应被填充数据库中的性能关键性最高的数据。性能关键性较低的数据可能驻留在较低成本的闪存或磁盘上。当然,如果您的数据库足够小,则可以将所有表填充到 IM 列库中。Database In-Memory 为表和实例化视图添加新的 INMEMORY 属性。
我们可以在
表空间、表、(子)分区和实例化视图中启用 INMEMORY 属性。
如果在表空间级别启用此属性,则默认情况下将为 IMCOLUMN 存储启用表空间中的所有表和实例化视图。
alter tablespace quest INMEMORY;
如果在表级别启用此属性,则应将表的所有列都填充到 IMCOLUMN 存储中。但是,您可以将列的子集仅填充到 IMCOLUMN 存储中。
Alter table quest_tab INMEMORY NO Inmemory (EMP);
同样,对于分区表
Alter table quest_tab INMEMORY MODIFY Partition quest_part_1 No Inmemory;
后台进程:
IMCO:IMCO 后台进程会启动已启用 in-memory 且优先级为 LOW/MEDIUM/HIGH/CRITICAL 的对象的填充(预填充)。
SMCO:SMCO 动态地产生从属进程 (Wnnn) 以实施这些任务。
Wnnn:Wnnn 进程执行 in-memory 填充和 in-memory 重新填充任务,以填充或重新填充已启用 in-memory 的对象。
对象在数据库打开后立即被填充到 IM 列存储的优先化列表中,或者在首次扫描(查询)后被填充到 IM 列存储中。填充对象的顺序由关键字 PRIORITY 控制,分为五个级别。默认 PRIORITY 为 NONE,这意味着仅在第一次扫描对象后才填充对象
由 INMEMORY 分句的 PRIORITY 子句控制的不同优先级级别
优先级级别 说明
CRITICAL 数据库打开后立即填充对象
HIGH 填充所有 CRITICAL 对象后填充此对象
MEDIUM 在填充所有 CRITICAL 和 HIGH 对象后填充中此对象
LOW 填充所有 CRITICAL、HIGH 和 MEDIUM 对象后填充此对象
NONE 只有在第一次扫描后时才会填充任何此对象(默认值)
小于 64KB 的对象不会填充到内存中,因为内存在 1MB 区块中分配致使这些对象在 IM 列存储中浪费大量空间。
例如:alter table quest inmemory priority critical;
In-Memory 压缩技术:
IM 列存储使用为访问速度而优化的特殊压缩格式,而不是存储缩减。数据库通过以下方式提升速度:
- 压缩格式使数据库可以减少为每列处理的内存量。SQL 直接在压缩列上执行。
- 数据库使用 SIMD 矢量(阵列)指令在单 CPU 时钟周期内处理列值阵列。数据库可将多个值存储在一个矢量中,从而通过 SIMD 矢量处理最大限度地提高性能优势。
In-memory 的压缩是使用关键字 MEMCOMPRESS(INMEMORY 属性的子句)指定。有六个级别,每个级别都提供不同级别的压缩和性能。
No Memcompress:数据填充至 In-Memory,无压缩。
Memcompress for DML:它主要用于 DML 性能和最少的压缩。
Memcompress for Query Low:针对查询性能进行了优化(默认值)。
Memcompress for Query High:针对查询性能和节省空间进行了优化
Memcompress for Capacity Low:与查询“高和低”相比,节省更多空间
Memcompress for Capacity High:针对空间节省进行了优化,并且性能稍低。
压缩率可能会从 2-20 倍不等,具体取决于所选的压缩选项、数据类型和表中的内容。
例如:alter table quest inmemory memcompress for query high;
RAC 上的 In-Memory 列存储:
在群集环境中,每个节点都有自己的列存储。群集中的每个节点都应保持与 IM 列存储相同的大小。默认情况下,填充到内存中的所有对象都将分布在群集中的所有 IM 列存储中。“INMEMORY”属性的两个附加子句(DISTRIBUTE 和 DUPLICATE)(仅限 Enineered 系统)控制对象在群集中 IM 列存储中的分布。
分布:
在群集中分布的对象通过分布子句进行控制。您可以按以下方式分布对象
按行范围分布 — 将对象按行分布到不同节点
按分区分布 — 将分区分布到群集中的节点
按子分区分布 — 将子分区分布到不同的节点。
例如:alter table quest inmemory distribute by partition;
在这里,需要重点指出的是,Oracle In-Memory RAC 是查询的
shared-nothing 架构,即,如果您对内存内数据对象发出查询(假设对象在两个 IM 列存储中分布),只能访问仿射节点中的数据,这意味着不会在群集中的所有实例之间共享 IMCU(Inmemory 压缩单元)。
因此,您可以将
并行度 (DOP) 设置为 AUTO。并行查询协调器识别 IMCU 位置的其他实例。如果您无法将 DOP 设置为 AUTO,则并行查询协调器不会使用 IMCU 的其他实例。
将并行度设置为 auto
alter system set parallel_degree_policy=AUTO scope=both sid='*';
复制:
为了提高可用性,对象被复制到所有实例中。您可以使用重复的子句来指定 inmemory 表存储在群集中的所有实例中。对于未设计的系统,此选项将不起作用。
例如:alter table quest inmemory duplicate all;
查询表存储在所有实例中。
监视内存中对象:
为监控内存中对象,oracle 引入了两个新的 V$ 视图
v$IM_SEGMENTS 或 v$IM_USER_SEGMENTS 和 v$IM_COLUMN_LEVEL。
通过这些视图,我们可以了解当前填充到 IMCOLUMN 存储中的对象数。
例如:
set linesize 256
set pagesize 999
select segment_name,ROUND(SUM(BYTES)/1024/1024/1024,2) "DATA GB",
ROUND(SUM(INMEMORY_SIZE)/1024/1024/1024,2) "IN-MEM GB",
ROUND(SUM(BYTES-BYTES_NOT_POPULATED)*100/SUM(BYTES),2) "% IN_MEM",
ROUND(SUM(BYTES-BYTES_NOT_POPULATED)/SUM(INMEMORY_SIZE),2) "COMP RATIO"
from V$IM_SEGMENTS
group by owner,segment_name
order by SUM(bytes) desc;
SEGMENT_NAME ORIG GB IN-MEM GB % IN_MEM COMP RATIO
H_LINEITEM 317.27 68.2 88.77 4.13
H_PARTSUPP 35.17 21.04 100 1.67
例如:
set linesize 256
set pagesize 999
set verify off
col OBJECT format a30
SELECT owner||'.'||table_name OBJECT,
inmemory INMEMORY,inmemory_priority PRIORITY,
inmemory_distribute DISTRIBUTE,inmemory_compression COMPRESSION,
inmemory_duplicate DUPLICATE
FROM all_tables
where owner='QUEST'
ORDER BY inmemory, owner||'.'||table_name;
OBJECT INMEMORY PRIORITY DISTRIBUTE COMPRESSION DUPLICATE
H_NATION ENABLED CRITICAL AUTO FOR QUERY HIGH NO DUPLICATE
H_REGION ENABLED CRITICAL AUTO FOR QUERY HIGH NO DUPLICATE
H_CUSTOMER
H_SUPPLIER
在上面的示例中,您将看到两个表 — Customer 和 Supplier — 没有“INMEMORY”列的值。INMEMORY 属性是段级别属性。Customer 和 Supplier 均为分区表,因此是逻辑对象。这些表的 INMEMORY 属性将在 *_TAB_ (SUB) PARTITIONS 中的分区或子分区级别记录。
另外三列— INMEMORY_PRIORITY、INMEMORY_DISTRIBUTE 和 INMEMORY_COMPRESSION — 还被添加到 * _TABLES 视图中,以指示每个表的当前 InMemory 属性。