首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >第四章 为In-Memory 启用填充对象(IM-4.1 第一部分)

第四章 为In-Memory 启用填充对象(IM-4.1 第一部分)

作者头像
Yunjie Ge
发布2022-04-23 09:33:50
发布2022-04-23 09:33:50
4K0
举报
文章被收录于专栏:数据库与编程数据库与编程

IM系列文章:第四章 为In-Memory 填充启用对象(IM-4.1第一部分)

4 为In-Memory填充(population)启用对象

本章介绍如何在IM列存储中启用和禁用填充对象,包括设置压缩和优先级选项。

本章包含以下主题:

  • 关于 In-Memory 填充当数据库从磁盘读取现有行格式数据,将其转换为列格式,然后将其存储在IM列存储中时,发生In-Memory 填充 (population)。只有具有 INMEMORY属性的对象才有资格进行填充。
  • 启用和禁用IM列存储的表 通过在CREATE TABLEALTER TABLE 语句中包含 INMEMORY 子句来启用IM列存储的表。通过在CREATE TABLEALTER TABLE 语句中包含 NO INMEMORY 子句来禁用IM列存储的表。
  • 启用和禁用内存表的列 您可以为单独的列指定 INMEMORY 子句。非虚拟列和In-Memory虚拟列(IM虚拟列)都有资格进入IM列存储。
  • 启用和禁用IM列存储的表空间 您可以启用或禁用IM列存储的表空间。
  • 启用和禁用IM列存储的物化视图 您可以为IM列存储启用和禁用物化视图。
  • In-Memory对象的强制填充:教程 启用In-Memory填充的对象不会立即填充该对象。
  • 为IM列存储启用ADO 信息生命周期管理(ILM)是一组用于管理从创建到归档或删除的数据的过程和策略。

关于In-Memory 填充

当数据库从磁盘读取现有行格式数据,将其转换为列格式,然后将其存储在IM列存储中时,发生In-Memory填充(population)(填充)。只有具有 INMEMORY 属性的对象才有资格进行填充。

此部分包含以下主题:

  • In-Memory 填充的目的 IM列存储不会自动将数据库中的所有对象加载到IM列存储中。
  • In-Memory填充如何工作 您可以指定数据库在数据库实例启动时或访问 INMEMORY 对象时填充IM列存储中的对象。填充算法也会因使用单实例还是Oracle RAC而有所不同。
  • In-Memory 填充的控制 使用数据定义语言(DDL)语句中的INMEMORY子句指定哪些对象适合填充到IM列存储中。您可以启用表空间、表、分区和物化视图。

In-Memory 填充的目的

IM列存储不会自动将数据库中的所有对象加载到IM列存储中。

如果不使用DDL将任何对象指定为 INMEMORY,则IM列存储器保持为空。要将行从用户指定的 INMEMORY对象转换为列格式,以便它们可用于分析查询,需要填充。

将磁盘上的现有数据转换为列格式的填充与将数据加载到IM列存储中的重新填充不同。由于IMCU是只读结构,因此当行更改时,Oracle数据库不会填充它们。相反,数据库在事务日志中记录行更改,然后创建新的IMCU作为重新填充的一部分。

In-Memory 填充如何工作

您可以指定数据库在数据库实例启动时或访问INMEMORY 对象时填充IM列存储中的对象。填充算法也会因使用单实例还是Oracle RAC而有所不同。

此部分包含以下主题:

  • In-Memory 填充优先级 DDL语句包括 INMEMORY PRIORITY子句,它提供对群体队列的更多控制。
  • 后台进程如何填充IMCU 在填充期间,数据库以其行格式从磁盘读取数据,扭转行以创建列,然后将数据压缩到。
In-Memory 填充优先级

DDL语句包括 INMEMORY PRIORITY 子句,它提供对群体队列的更多控制。

注:

INMEMORY PRIORITY 子句控制填充的优先级,但不控制填充的速度。

优先级级别设置适用于整个表、分区或子分区,而不适用于不同的列子集。在对象上设置 INMEMORY 属性意味着该对象是IM列存储中的填充的候选对象。这并不意味着数据库立即填充对象。 Oracle数据库管理优先级如下:

  • 按需(On-demand)填充 默认情况下,INMEMORY PRIORITY 参数设置为 NONE。在这种情况下,数据库只在通过全表扫描访问对象时填充该对象。如果对象从未被访问过,或者只能通过索引扫描或者通过rowid获取,那么将不会发生填充。
  • 优先级(Priority-based)的填充PRIORITY 设置为 NONE以外的值时,Oracle数据库使用内部管理的优先级队列自动填充对象。在这种情况下,全扫描不是填充的必要条件。数据库执行以下操作:

·在数据库实例重新启动后自动填充IM列存储中的列数据

·根据指定的优先级排列 INMEMORY 对象的队列数

例如,使用 INMEMORY PRIORITYCRITICAL 更改的表优先于使用 INMEMORY PRIORITYHIGH修改的表, INMEMORY PRIORITY HIGH的表优先于 INMEMORY PRIORITYLOW修改的表。如果IM列存储空间不足,则Oracle数据库在空间可用之前不会填充其他对象。

· 等待从 ALTER TABLEALTER MATERIALIZED VIEW 语句返回,直到对象的更改记录在IM列存储中

在IM列存储中填充了段之后,数据库只会在删除或移动段时将其逐出,或者使用 NO INMEMORY 属性更新段。您可以手动或通过ADO策略驱逐段。

示例4-1 IM列存储中的对象的填充

在完成此示例之前,必须为数据库启用IM列存储。

1. 以管理员身份登录到数据库,然后查询customers表,如下所示:

代码语言:javascript
复制
SELECT cust_id, cust_last_name, cust_first_name 
代码语言:javascript
复制
FROM   sh.customers 
代码语言:javascript
复制
WHERE  cust_city = 'Hyderabad' 
代码语言:javascript
复制
AND    cust_income_level LIKE 'C%' 
代码语言:javascript
复制
AND    cust_year_of_birth > 1960;

2. 显示查询的执行计划:

代码语言:javascript
复制
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));
代码语言:javascript
复制
SQL_ID  frgk9dbaftmm9, child number 0
代码语言:javascript
复制
-------------------------------------
代码语言:javascript
复制
SELECT cust_id, cust_last_name, cust_first_name FROM   sh.customers
代码语言:javascript
复制
WHERE  cust_city = 'Hyderabad' AND    cust_income_level LIKE 'C%' AND
代码语言:javascript
复制
 cust_year_of_birth > 1960
代码语言:javascript
复制
代码语言:javascript
复制
Plan hash value: 2008213504
代码语言:javascript
复制
代码语言:javascript
复制
-------------------------------------------------------------------------------
代码语言:javascript
复制
| Id| Operation         | Name      |Starts|E-Rows|A-Rows|   A-Time   |Buffers|
代码语言:javascript
复制
-------------------------------------------------------------------------------
代码语言:javascript
复制
|  0| SELECT STATEMENT  |           |     1|      |    6 |00:00:00.01 |   1523|
代码语言:javascript
复制
|* 1|  TABLE ACCESS FULL| CUSTOMERS |     1|    6 |    6 |00:00:00.01 |   1523|
代码语言:javascript
复制
-------------------------------------------------------------------------------
代码语言:javascript
复制
代码语言:javascript
复制
Predicate Information (identified by operation id):
代码语言:javascript
复制
---------------------------------------------------
代码语言:javascript
复制
代码语言:javascript
复制
   1 - filter(("CUST_CITY"='Hyderabad' AND "CUST_YEAR_OF_BIRTH">1960 AND
代码语言:javascript
复制
              "CUST_INCOME_LEVEL" LIKE 'C%'))

3. 在IM列存储中启用 sh.customers 表以进行填充:

代码语言:javascript
复制
ALTER TABLE sh.customers INMEMORY;

上面的语句使用默认优先级NONE。需要进行完全扫描才能填充没有优先级的对象。

4. 要确定来自 sh.customers 表的数据是否已填充到IM列存储中,请执行以下查询(包括样例输出):

代码语言:javascript
复制
SELECT SEGMENT_NAME, POPULATE_STATUS 
代码语言:javascript
复制
FROM   V$IM_SEGMENTS 
代码语言:javascript
复制
WHERE  SEGMENT_NAME = 'CUSTOMERS';
代码语言:javascript
复制
代码语言:javascript
复制
no rows selected

在这种情况下,IM列存储中不会填充任何段,因为尚未扫描 sh.customers 表。

5. 使用与步骤1中相同的语句查询 sh.customers

代码语言:javascript
复制
SELECT cust_id, cust_last_name, cust_first_name 
代码语言:javascript
复制
FROM   sh.customers 
代码语言:javascript
复制
WHERE  cust_city = 'Hyderabad' 
代码语言:javascript
复制
AND    cust_income_level LIKE 'C%' 
代码语言:javascript
复制
AND    cust_year_of_birth > 1960;

6. 查询游标显示数据库执行完整扫描并访问IM列存储:

代码语言:javascript
复制
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));
代码语言:javascript
复制
SQL_ID  frgk9dbaftmm9, child number 0
代码语言:javascript
复制
-------------------------------------
代码语言:javascript
复制
SELECT cust_id, cust_last_name, cust_first_name FROM   sh.customers
代码语言:javascript
复制
WHERE  cust_city = 'Hyderabad' AND    cust_income_level LIKE 'C%' AND
代码语言:javascript
复制
 cust_year_of_birth > 1960
代码语言:javascript
复制
代码语言:javascript
复制
Plan hash value: 2008213504
代码语言:javascript
复制
代码语言:javascript
复制
---------------------------------------------------------------------------------
代码语言:javascript
复制
| Id| Operation           | Name            |Starts|E-Rows|A-Rows|A-Time|Buffers|
代码语言:javascript
复制
---------------------------------------------------------------------------------
代码语言:javascript
复制
|  0| SELECT STATEMENT           |           |    1|     | 6 |00:00:00.02| 1523 |
代码语言:javascript
复制
|* 1|  TABLE ACCESS INMEMORY FULL| CUSTOMERS |    1|    6| 6 |00:00:00.02| 1523 |
代码语言:javascript
复制
---------------------------------------------------------------------------------
代码语言:javascript
复制
代码语言:javascript
复制
Predicate Information (identified by operation id):
代码语言:javascript
复制
---------------------------------------------------
代码语言:javascript
复制
代码语言:javascript
复制
   1 - inmemory(("CUST_CITY"='Hyderabad' AND "CUST_YEAR_OF_BIRTH">1960 AND
代码语言:javascript
复制
              "CUST_INCOME_LEVEL" LIKE 'C%'))
代码语言:javascript
复制
       filter(("CUST_CITY"='Hyderabad' AND "CUST_YEAR_OF_BIRTH">1960 AND
代码语言:javascript
复制
              "CUST_INCOME_LEVEL" LIKE 'C%'))

7. 再次查询 V$IM_SEGMENTS (包括样例输出):

代码语言:javascript
复制
COL SEGMENT_NAME FORMAT a20
代码语言:javascript
复制
代码语言:javascript
复制
SELECT SEGMENT_NAME, POPULATE_STATUS 
代码语言:javascript
复制
FROM   V$IM_SEGMENTS 
代码语言:javascript
复制
WHERE  SEGMENT_NAME = 'CUSTOMERS';
代码语言:javascript
复制
代码语言:javascript
复制
SEGMENT_NAME         POPULATE_STATUS
代码语言:javascript
复制
-------------------- ---------------
代码语言:javascript
复制
CUSTOMERS            COMPLETED

POPULATE_STATUS 中的值COMPLETED 意味着该表填充在IM列存储中。

  1. DBA_FEATURE_USAGE_STATISTICS 视图确认数据库使用IM列存储检索结果:
代码语言:javascript
复制
COL NAME FORMAT a25
代码语言:javascript
复制
SELECT ul.NAME, ul.DETECTED_USAGES 
代码语言:javascript
复制
FROM   DBA_FEATURE_USAGE_STATISTICS ul 
代码语言:javascript
复制
WHERE  ul.VERSION= (SELECT MAX(u2.VERSION) 
代码语言:javascript
复制
                    FROM   DBA_FEATURE_USAGE_STATISTICS u2 
代码语言:javascript
复制
                    WHERE  u2.NAME = ul.NAME 
代码语言:javascript
复制
                    AND    ul.NAME LIKE '%Column Store%');
代码语言:javascript
复制
代码语言:javascript
复制
NAME                      DETECTED_USAGES
代码语言:javascript
复制
------------------------- ---------------
代码语言:javascript
复制
In-Memory Column Store    1
后台进程如何填充IMCU

在填充期间,数据库以其行格式从磁盘读取数据,扭转行以创建列,然后将数据压缩到内存压缩单元(IMCU)。

工作进程(Wnnn)填充IM列存储中的数据。每个工作进程对来自对象的数据库块的子集进行操作。Population是一种流式传输机制,同时压缩数据并将其转换为列式格式。

INMEMORY_MAX_POPULATE_SERVERS 初始化参数指定要用于IM列存储填充的工作进程的最大数目。默认情况下,设置为 CPU_COUNT 的一半。将此参数设置为适合您环境的值。更多的工作进程导致更快的填充,但他们使用更多的CPU资源。较少的工作进程导致较慢的填充,这减少了CPU开销。

注:

如果INMEMORY_MAX_POPULATE_SERVERS 设置为 0,则禁用填充。

In-Memory 填充控制

使用数据定义语言(DDL)语句中的 INMEMORY 子句指定哪些对象适合填充到IM列存储中。您可以启用表空间、表、分区和物化视图。

此部分包含以下主题:

  • INMEMORY子句 INMEMORY 是段级属性,而不是列级属性。但是,可以将INMEMORY 属性应用于特定对象中的列子集。
  • In-Memory 填充优先级选项 为IM列存储启用数据库对象时,可以启用Oracle数据库以控制在IM列存储中填充对象的时间(默认),或者,您可以指定确定对象在填充队列中的优先级的优先级。
  • IM列存储压缩方法 根据您的要求,您可以在不同级别压缩内存中的对象。
  • Oracle Compression Advisor Oracle Compression Advisor 估计您可以使用MEMCOMPRESS子句实现的压缩率。顾问程序使用 DBMS_COMPRESSION 接口。
INMEMORY 子句

INMEMORY 是段级属性,而不是列级属性。但是,可以将INMEMORY 属性应用于特定对象中的列子集。

要启用或禁用IM列存储的对象,请在以下任何语句中指定 INMEMORY 子句:

· CREATE TABLESPACE ALTER TABLESPACE

默认情况下,为IM列存储启用表空间中的所有表和物化视图。表空间中的单个表和物化视图可能具有不同的 INMEMORY属性。单个数据库对象的属性将覆盖表空间的属性。

· CREATE TABLE ALTER TABLE

默认情况下,IM列存储填充表中的所有非虚拟列。您可以为表指定全部或部分列。例如,您可以将 oe.product_information 中的 weight_classcatalog_url 列从合格(eligibility)中排除。对于分区表,可以填充IM列存储中的所有分区或子集的分区。默认情况下,对于分区表,所有表分区都继承 INMEMORY 属性。

· CREATEMATERIALIZED VIEW ALTER MATERIALIZEDVIEW

对于分区物化视图,可以填充IM列存储中的所有分区或子集的分区。

DBA_TABLES 视图中的INMEMORY列指示哪些表具有INMEMORY属性集(ENABLED)或未设置(DISABLED)。

以下对象不适用于IM列存储中的填充:

· 索引

· 索引组织表

· Hash集群

· SYS 用户拥有并存储在SYSTEMSYSAUX 表空间中的对象

如果为IM列存储启用表,并且它包含以下任何类型的列,则不会在IM列存储中填充这些列:

· 行外列(数组、嵌套表列和行外LOB)

· 使用LONG或LONG RAW数据类型的列

· 扩展数据类型列

示例4-2将表指定为INMEMORY

假设您以用户 sh连接到数据库。使用默认压缩级别 FOR QUERY LOW(请参见 “In-Memory压缩”)启用IM列存储中的用于填充的 customers 表:

代码语言:javascript
复制
SQL> SELECT TABLE_NAME, INMEMORY FROM USER_TABLES WHERE TABLE_NAME = 'CUSTOMERS';
代码语言:javascript
复制
代码语言:javascript
复制
TABLE_NAME INMEMORY
代码语言:javascript
复制
---------- --------
代码语言:javascript
复制
CUSTOMERS  DISABLED
代码语言:javascript
复制
代码语言:javascript
复制
SQL> ALTER TABLE customers INMEMORY;
代码语言:javascript
复制
代码语言:javascript
复制
Table altered.
代码语言:javascript
复制
代码语言:javascript
复制
SQL> SELECT TABLE_NAME, INMEMORY, INMEMORY_COMPRESSION FROM USER_TABLES WHERE TABLE_NAME='CUSTOMERS';
代码语言:javascript
复制
代码语言:javascript
复制
TABLE_NAME INMEMORY INMEMORY_COMPRESS
代码语言:javascript
复制
---------- -------- -----------------
代码语言:javascript
复制
CUSTOMERS  ENABLED  FOR QUERY LOW
In-Memory 填充优先级选项

为IM列存储启用数据库对象时,可以启用Oracle数据库以控制在IM列存储中填充对象的时间(默认),或者,您可以指定确定对象在填充队列中的优先级的优先级。

Oracle SQL包括一个 INMEMORY PRIORITY 子句,可以更好地控制队列以进行填充。例如,在填充其他数据库对象的数据之前填充数据库对象的数据可能更重要或更不重要。

下表描述了支持的优先级。

表4-1填充IM列存储中的数据库对象的优先级

当多个数据库对象的优先级等级不是NONE时,Oracle数据库将根据优先级将要填充到IM列存储中的数据库对象的所有数据排队。首先填充具有CRITICAL 优先级的数据库对象; 接下来填充具有HIGH优先级级别的数据库对象,等等。如果IM列存储中没有剩余空间,则不会在其中填充任何其他对象,直到有足够的空间可用。

注:

如果将所有对象指定为CRITICAL,则数据库不会将任何对象视为比任何其他对象更关键。

重新启动数据库时,启动期间将在IM列存储中填充优先级别不为NONE的数据库对象的所有数据。对于优先级为非NONE的数据库对象,在DDL更改记录到IM列存储之前,不会返回涉及数据库对象的 ALTER TABLEALTERMATERIALIZED VIEWDDL语句。

注:

· 优先级设置必须适用于整个表或表分区。不允许为表中不同的列子集指定不同的IM列存储优先级。

· 如果磁盘上的段为64 KB或更小,则它不会填充到IM列存储中。因此,可能不会填充为IM列存储启用的某些小型数据库对象。

IM列存储压缩方法

根据您的要求,您可以在不同级别压缩内存中的对象。

通常,压缩是一种节省空间的机制。而IM列存储可以压缩数据,并使用一套新的算法提高查询性能。如果使用 FOR DMLFOR QUERY 选项压缩列数据,则SQL查询直接对压缩数据执行。因此,扫描和过滤操作在小得多的数据量上执行。数据库仅在结果集需要数据时才解压缩数据。

VIM_SEGMENTS 和 VIM_COLUMN_LEVEL 视图指示当前的压缩级别。您可以使用相应的ALTER命令更改压缩级别。如果当前在IM列存储中填充了表,并且如果更改了 PRIORITY之外的表的任何 INMEMORY 属性,则数据库会从IM列存储中逐出该表。重新填充行为取决于 INMEMORY 设置。

下表总结了IM列存储中支持的数据压缩方法。

表4-2 IM列存储压缩方法

在SQL语句中,MEMCOMPRESS 关键字必须在INMEMORY 关键字前面。

Oracle Compression Advisor

Oracle Compression Advisor估计您可以使用MEMCOMPRESS 子句实现的压缩率。顾问程序使用DBMS_COMPRESSION接口。

对表运行DBMS_COMPRESSION.GET_COMPRESSION_RATIO时,Oracle数据库会分析一个示例行。因此,Oracle压缩顾问提供了一个表,在填充到IM列存储后,表实现的压缩结果的良好估计。

(待续)

山东Oracle用户组(Shandong Oracle User Group),简称:SDOUG,是一个充满朝气、年轻的非营利性组织,旨在为济南及周边地区技术爱好者提供一个交流平台。SDOUG会不定期组织线下技术分享活动,促进本地区及周边IT技术的发展、帮助技术爱好者提高自己。分享技术、分享快乐,SDOUG在路上。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 山东Oracle用户组 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 4 为In-Memory填充(population)启用对象
    • 关于In-Memory 填充
      • In-Memory 填充的目的
      • In-Memory 填充如何工作
      • In-Memory 填充控制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档