Oracle 12C 列式存储

梁铭图 2019-12-13 13:00:00
 

​作者介绍

梁铭图,新炬网络首席架构师,十多年数据库运维、数据库设计、数据治理以及系统规划建设经验,拥有Oracle OCM、Togaf企业架构师(鉴定级)、IBM CATE等认证,曾获dbaplus年度MVP以及华为云MVP等荣誉,并参与数据资产管理国家标准的编写工作。在数据库运维管理和架构设计、运维体系规划、数据资产管理方面有深入研究。

 

一、数据库的行、列之争

 

数据库业界以数据的存储方式一般有以行存储和以列存储两种。

 

传统的关系型数据库,如 Oracle、DB2、MySQL、SQL SERVER 等采用行式存储法(Row-based),在基于行式存储的数据库中, 数据是按照行数据为基础逻辑存储单元进行存储的, 一行中的数据在存储介质中以连续存储形式存在。

 

列式存储(Column-based)是相对于行式存储来说的,新兴的 Hbase、HP Vertica、EMC Greenplum 等分布式数据库均采用列式存储。在基于列式存储的数据库中, 数据是按照列为基础的逻辑存储单元进行存储的,一列中的数据在存储介质中以连续存储形式存在。
 

 

针对于一些数据分析类的应用场景,如统计企业每种产品的年销售量,用SQL来表达为:

 

 

Select year,product_id, sum(sale_amount) 

From sale 

Where year >= 2010

Group by year,product_id

Order by year,product_id;

 

SALE表存储了企业十多年的销售数据,表中有数十个列以及数十亿的记录数。此时,用行存储的数据库处理这个SQL时,就需要对整个表进行全表扫描,这个成本和代价均是非常巨大的。

 

此时,如果以列存储数据的数据库相对于大家都理解的以行存储模式,带来了以下优点:

 

  • 只访问查询涉及的列,如上述的例子,只需要访问year ,product_id,sale_amount三个列,而行式存储的数据库则需要对sale表全表扫描。这样可以大量降低系统I/O。

  • 每一列由一个线程来处理,即查询的并发处理性能高,可以充分利用计算机的并发处理能力,增加数据吞吐量

  • 数据类型一致,数据特征相似,可以高效压缩。所以可以大幅度提高压缩比,有利于系统 I/O和网络输出数据带宽的消耗。

 

所以以列存储的数据库往往用于海量数据分析和处理的OLAP的应用场景。

 

二、Oracle IN-MEMROY列存储

 

众所周知,Oracle从诞生之日就是一个以行存储的数据库。然而,面对着海量数据分析的需求,Oracle老大也坐不往了。从Oracle 12.1.0.2 开始,Oracle引入In-Memory Column Store 特性,即在SGA 中在单独开辟一块内存空间,以列存储的方式来存储对象,从而提升扫描的性能。IM column 存储并不能代替buffer cache,而是对内存区域的一个补充。

 

Oracle dual-format 架构允许数据同时存储在 buffer cache和 In memory Area中,但Oracle 并不需要2倍的内容空间,in-memroy column format ( In memory Area)会根据对象的大小,加载在内存中,但buffer cache 所需要的内存空间就会小很多。

 

In-Memory area 是在SGA中的一个区域,其大小由初始化参数INMEMORY_SIZE决定,默认为0,可以通过V$SGA视图查看大小。In-Memory area是一个静态区域,其大小不受AMM管理,如果修改INMEMORY_SIZE参数,必须重启实例才能生效,如果启用该特性,那么INMEMORY_SIZE最小值是100M。

 

1、启用IM列存储特性
 

 

在表、物化视图等具体对象启用IM列存储之前,必须先启用数据库的特性。启用很简单,设置INMEMORY_SIZE参数即可。该参数是一个静态参数,修改之后,需要重启实例才能生效。

 

 

SQL> show parameter inmemory_size

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

inmemory_size                        big integer 0

 

SQL> alter system set inmemory_size=200m scope=spfile;

SQL> startup;

ORACLE instance started.

 

Total System Global Area 1493172224 bytes

Fixed Size                  2924592 bytes

Variable Size             520097744 bytes

Database Buffers          738197504 bytes

Redo Buffers               13848576 bytes

In-Memory Area            218103808 bytes

Database mounted.

Database opened.

 

在启用之后,可以在SGA看到IN-MEMROY area大小的信息。

 

 

SQL> show sga

 

Total System Global Area 1493172224 bytes

Fixed Size                  2924592 bytes

Variable Size             520097744 bytes

Database Buffers          738197504 bytes

Redo Buffers               13848576 bytes

In-Memory Area            218103808 bytes

 

2、监测IM列存储
 

 

查看IM相关的动态性能视图,每个视图的作用,可以查看官方手册。

 

 

SQL> select object_name,object_type,status from dba_objects where object_name like 'V$IM%';

OBJECT_NAME                    OBJECT_TYPE             STATUS

------------------------------ ----------------------- -------

V$IM_COLUMN_LEVEL              SYNONYM                 VALID

V$IM_COL_CU                    SYNONYM                 VALID

V$IM_HEADER                    SYNONYM                 VALID

V$IM_SEGMENTS                  SYNONYM                 VALID

V$IM_SEGMENTS_DETAIL           SYNONYM                 VALID

V$IM_SEG_EXT_MAP               SYNONYM                 VALID

V$IM_SMU_CHUNK                 SYNONYM                 VALID

V$IM_SMU_HEAD                  SYNONYM                 VALID

V$IM_TBS_EXT_MAP               SYNONYM                 VALID

V$IM_USER_SEGMENTS             SYNONYM                 VALID

 

SQL> select object_name,object_type,status from dba_objects where object_name like 'V$INM%';

OBJECT_NAME                    OBJECT_TYPE             STATUS

------------------------------ ----------------------- -------

V$INMEMORY_AREA                SYNONYM                 VALID

 

创建TEST表,再使用INMEMORY。

 

 

SQL> create table test as select * from dba_objects;

Table created.

 

SQL> alter table test inmemory;

Table altered.

 

查看v$im_segments、v$im_user_segments视图可以查看当前在列存储中的对象。

 

 

SQL> select v.owner, v.segment_name,v.bytes orig_size,v.inmemory_size in_mem_size,v.bytes / v.inmemory_size comp_ratio from v$im_segments v;

 

no rows selected

 

可以看到,这里没有返回记录,这是因为根据默认的策略,对象第一次使用的时候,才会加载到IM中。可以通过dba_tables视图来确认,在12C中,该视图多了与IM有关的列。

 

 

SQL> select table_name, inmemory, inmemory_priority, inmemory_distribute, inmemory_compression, inmemory_duplicate  

from dba_tables where table_name='TEST';

 

TABLE_NAME  INMEMORY    INMEMORY INMEMORY_DISTRI INMEMORY_COMPRESS INMEMORY_DUPL

-------------------- -------- -------- --------------- ----------------- -------------

TEST         ENABLED      NONE      AUTO            FOR QUERY LOW     NO DUPLICATE

 

3、使用pdb中的非系统用户测试
 

 

1)表级的IM

 

①创建表时指定IM

 

 

SQL> create table test1 inmemory as select * from dba_objects;

Table created.

 

SQL> select v.owner, v.segment_name,v.bytes orig_size,v.inmemory_size in_mem_size,v.bytes / v.inmemory_size comp_ratio from v$im_segments v;

no rows selected

 

SQL> select count(*) from test1;

  COUNT(*)

----------

     90940

 

SQL> set line 300 pages 300

SQL> col owner for a10

SQL> col segment_name for a10

SQL> select v.owner, v.segment_name,v.bytes orig_size,v.inmemory_size in_mem_size,v.bytes / v.inmemory_size comp_ratio from v$im_segments v;

OWNER      SEGMENT_NA  ORIG_SIZE IN_MEM_SIZE COMP_RATIO

---------- ---------- ---------- ----------- ----------

ZWF        TEST1        13631488     4325376 3.15151515

 

这次可以查到记录了。

 

②使用alter来修改

 

 

SQL> create table test2 as select * from dba_objects;

Table created.

 

SQL> alter table test2 inmemory;

Table altered.

 

SQL> select count(*) from test2;

  COUNT(*)

----------

     90941

 

SQL> select v.owner, v.segment_name,v.bytes orig_size,v.inmemory_size in_mem_size,v.bytes / v.inmemory_size comp_ratio from v$im_segments v;

OWNER      SEGMENT_NA  ORIG_SIZE IN_MEM_SIZE COMP_RATIO

---------- ---------- ---------- ----------- ----------

ZWF        TEST1        13631488     4325376 3.15151515

ZWF        TEST2        13631488     4325376 3.15151515

 

2)取消对象的IM

 

对已经启用IM的对象,可以取消掉,使用alter no inmemory即可。

 

 

SQL> alter table test1 no inmemory;

Table altered.

 

SQL> select table_name, inmemory, inmemory_priority, inmemory_distribute, inmemory_compression, inmemory_duplicate  from dba_tables where table_name in ('TEST1');

 

TABLE_NAME INMEMORY INMEMORY INMEMORY_DISTRI INMEMORY_COMPRESS INMEMORY_DUPL

---------- -------- -------- --------------- ----------------- -------------

TEST1      DISABLED

 

3)表空间级的IM

 

可以在创建表空间的时候指定INMEMORY选项,来启用IM功能,也可以使用ALTER TABLESPACE来启用创建时没有启用IM的表空间。在表空间启用IM column store的情况下, 其上所有的表和物化视图都默认启用IM。

 

当表空间启用IM的时,也可以对表或者物化视图指定不同的IM策略。这样这些独立的表就会按照自己指定的IM策略在运行,而不是使用表空间默认的策略。

 

当然,取消IM功能也类似,在CREATE TABLESPACE 或者 ALTER TABLESPACE的时候指定NO IMMEMORY选项即可。

 

IM属性,可以通过dba_tablespaces视图查看。

 

①使用默认IM策略(MEMCOMPRESS FOR QUERY,PRIORITY NONE)来创建表空间

 

 

SQL> create tablespace tbs_test datafile '+data' size 10m online default inmemory;

Tablespace created.

SQL> select tablespace_name, def_inmemory,def_inmemory_priority, def_inmemory_distribute, def_inmemory_compression from dba_tablespaces;

 

TABLESPACE_NAME                DEF_INME DEF_INME DEF_INMEMORY_DI DEF_INMEMORY_COMP

------------------------------ -------- -------- --------------- -----------------

SYSTEM                         DISABLED

SYSAUX                         DISABLED

TEMP                           DISABLED

USERS                          DISABLED

TBS_TEST                       ENABLED  NONE     AUTO            FOR QUERY LOW

 

SQL> create table test3  tablespace tbs_test as select * from dba_tables where rownum<30;

Table created.

 

SQL> select table_name, inmemory, inmemory_ priority, inmemory_distribute, inmemory_compression, inmemory_duplicate  from dba_tables where table_name like 'TEST%';

 

TABLE_NAME INMEMORY INMEMORY INMEMORY_DISTRI INMEMORY_COMPRESS INMEMORY_DUPL

---------- -------- -------- --------------- ----------------- -------------

TEST3      ENABLED  NONE     AUTO            FOR QUERY LOW     NO DUPLICATE

TEST2      ENABLED  NONE     AUTO            FOR QUERY LOW     NO DUPLICATE

TEST1      DISABLED

 

从上面可以看到虽然创建TEST3表时没有指定IM,但是其所属的表空间指定了IM,所以相应的TEST3表是启用了IM的。

 

②修改IM策略

 

从上面测试可以看到,修改了表空间的IM策略,但是TEST3表的IM策略没有改变,新创建的TEST4表才使用了新的IM策略。

 

 

SQL> alter tablespace tbs_test default inmemory memcompress for capacity high priority low;

Tablespace altered.

 

SQL> select table_name,inmemory,inmemory_priority,inmemory_distribute,inmemory_compression,inmemory_duplicate  from dba_tables where table_name like 'TEST%';

 

TABLE_NAME INMEMORY INMEMORY INMEMORY_DISTRI INMEMORY_COMPRESS INMEMORY_DUPL

---------- -------- -------- --------------- ----------------- -------------

TEST3      ENABLED  NONE     AUTO            FOR QUERY LOW     NO DUPLICATE

TEST2      ENABLED  NONE     AUTO            FOR QUERY LOW     NO DUPLICATE

TEST1      DISABLED

 

SQL> create table test4  tablespace tbs_test as select * from dba_tables where rownum<30;

 

Table created.

 

SQL> select table_name,inmemory,inmemory_priority,inmemory_distribute,inmemory_compression,inmemory_duplicate  from dba_tables where table_name like 'TEST%';

 

TABLE_NAME INMEMORY INMEMORY INMEMORY_DISTRI INMEMORY_COMPRESS INMEMORY_DUPL

---------- -------- -------- --------------- ----------------- -------------

TEST4      ENABLED  LOW      AUTO            FOR CAPACITY HIGH NO DUPLICATE

TEST3      ENABLED  NONE     AUTO            FOR QUERY LOW     NO DUPLICATE

TEST2      ENABLED  NONE     AUTO            FOR QUERY LOW     NO DUPLICATE

TEST1      DISABLED

 

③取消表空间的IM策略

 

 

SQL> alter tablespace tbs_test default no inmemory;

 

Tablespace altered.

 

从上面的测试可以看到,虽然表空间的IM策略取消了,但是之前创建的TEST3和TEST4两张表的IM策略还是启用的。

最新评论
访客 2023年08月20日

230721

访客 2023年08月16日

1、导入Mongo Monitor监控工具表结构(mongo_monitor…

访客 2023年08月04日

上面提到: 在问题描述的架构图中我们可以看到,Click…

访客 2023年07月19日

PMM不香吗?

访客 2023年06月20日

如今看都很棒

活动预告