作者介绍
梁铭图,新炬网络首席架构师,十多年数据库运维、数据库设计、数据治理以及系统规划建设经验,拥有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。
在表、物化视图等具体对象启用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
查看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
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策略还是启用的。
部署后为什么抓取不到慢日志呢
我好奇的是监控为什么不选择influxdb这种时序数据库?
“在读请求中先查询缓存,如果缓存命中则直接返回,如…
不错
让我受益很多 会持续关注的