当前位置: 首页 > news >正文

Oracle 19C In-Memory 列存储技术测试

测试时间:20250807
数据库版本:Oracle 19.27
表数据量:1000万行
==========================================================================================
结论:
1、未启用In-Memory和启用In-Memory,以下查询时间如下:
SELECT region, SUM(amount) 
FROM sales 
GROUP BY region;

未启用:2.94
启用:00.54

SELECT product_id, 
TO_CHAR(sale_date, 'YYYY-MM'), 
SUM(quantity), 
SUM(amount)
FROM sales
WHERE sale_date BETWEEN TO_DATE('2023-01-01', 'YYYY-MM-DD') 
AND TO_DATE('2023-12-31', 'YYYY-MM-DD')
GROUP BY product_id, TO_CHAR(sale_date, 'YYYY-MM')
ORDER BY product_id, TO_CHAR(sale_date, 'YYYY-MM');

未启用:3.14
启用:1.15s

这是1000万行表的测试,如果表更大,效果会更明显;启用IM后,执行计划TABLE ACCESS INMEMORY FULL,物理读为0。

2、启用压缩
CAPACITY HIGH级别:(ALTER TABLE sales INMEMORY MEMCOMPRESS FOR CAPACITY HIGH;)
POOL                       ALLOC_BYTES USED_BYTES
-------------------------- ----------- ----------
1MB POOL                    3001024512   74448896 <<<<<<<<<<<<<<<<<<<
64KB POOL                   1275068416    3604480

FOR QUERY LOW级别:(ALTER TABLE sales INMEMORY MEMCOMPRESS FOR QUERY LOW;)
POOL                       ALLOC_BYTES USED_BYTES
-------------------------- ----------- ----------
1MB POOL                    3001024512  294649856 <<<<<<<<<<<<<<<<<<<
64KB POOL                   1275068416    3604480

NO MEMCOMPRESS(不压缩):(ALTER TABLE sales INMEMORY NO MEMCOMPRESS;)
POOL                       ALLOC_BYTES USED_BYTES
-------------------------- ----------- ----------
1MB POOL                    3001024512  415236096 <<<<<<<<<<<<<<<<<<<
64KB POOL                   1275068416   19333120

说明:CAPACITY HIGH 74M左右;FOR QUERY LOW 294M左右;NO MEMCOMPRESS 415M左右;最高压缩和不压缩相差6倍左右。

==========================================================================================
检查是否有In-Memory Column Store组件。
SELECT * FROM v$option WHERE parameter = 'In-Memory Column Store';

1. 检查并配置In-Memory参数

-- 1.1 检查In-Memory是否启用
SHOW PARAMETER INMEMORY_SIZE;

-- 如果未启用或需要调整大小(需要重启数据库)
ALTER SYSTEM SET INMEMORY_SIZE=4G SCOPE=SPFILE;

-- 1.2 确认In-Memory Area状态
SELECT POOL, ALLOC_BYTES, USED_BYTES FROM V$INMEMORY_AREA;

2. 创建测试表并生成测试数据
-- 创建sales表
CREATE TABLE sales (
sale_id      NUMBER PRIMARY KEY,
product_id   NUMBER,
sale_date    DATE,
quantity     NUMBER,
amount       NUMBER,
region       VARCHAR2(50)
);

-- 生成测试数据(约1000万条)
DECLARE
v_start_date DATE := TO_DATE('2020-01-01', 'YYYY-MM-DD');
v_end_date DATE := TO_DATE('2023-12-31', 'YYYY-MM-DD');
v_days NUMBER := v_end_date - v_start_date;
v_regions VARCHAR2(200) := 'North,South,East,West,Central,Northeast,Northwest,Southeast,Southwest';
BEGIN
FOR i IN 1..10000000 LOOP
INSERT INTO sales VALUES (
i,
MOD(i, 1000) + 1,
v_start_date + MOD(i, v_days),
MOD(i, 10) + 1,
ROUND(DBMS_RANDOM.VALUE(10, 1000), 2),
REGEXP_SUBSTR(v_regions, '[^,]+', 1, MOD(i, 9) + 1)
);

IF MOD(i, 10000) = 0 THEN
COMMIT;
END IF;
END LOOP;
COMMIT;
END;
/

-- 收集统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'SALES');

3. 启用表的In-Memory特性
-- 3.1 将表sales加载到In-Memory列存储
ALTER TABLE sales INMEMORY MEMCOMPRESS FOR QUERY LOW;

-- 3.2 可选:指定关键列使用不同压缩率
ALTER TABLE sales 
INMEMORY MEMCOMPRESS FOR CAPACITY HIGH (amount, sale_date)
NO INMEMORY (region);

-- 3.3 验证In-Memory配置
SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY 
FROM DBA_TABLES 
WHERE TABLE_NAME = 'SALES';

TABLE_NAME INMEMORY_COMPRESS INMEMORY
---------- ----------------- --------
SALES      FOR QUERY LOW     NONE

-- 查看列级In-Memory设置
col owner for a10
col TABLE_NAME for a10
col COLUMN_NAME for a22
select * from v$im_column_level where TABLE_NAME= 'SALES';

   INST_ID OWNER         OBJ_NUM TABLE_NAME SEGMENT_COLUMN_ID COLUMN_NAME            INMEMORY_COMPRESSION           CON_ID
---------- ---------- ---------- ---------- ----------------- ---------------------- -------------------------- ----------
1 JOE            100882 SALES                      1 SALE_ID                DEFAULT                             0
1 JOE            100882 SALES                      2 PRODUCT_ID             DEFAULT                             0
1 JOE            100882 SALES                      3 SALE_DATE              DEFAULT                             0
1 JOE            100882 SALES                      4 QUANTITY               DEFAULT                             0
1 JOE            100882 SALES                      5 AMOUNT                 DEFAULT                             0
1 JOE            100882 SALES                      6 REGION                 DEFAULT                             0

4. 手动加载数据到内存并监控进度

-- 4.1 触发全表加载
SELECT /*+ FULL(sales) NO_PARALLEL(sales) */ COUNT(*) FROM sales;

-- 4.2 监控加载进度
SELECT SEGMENT_NAME, BYTES_NOT_POPULATED, POPULATE_STATUS 
FROM V$IM_SEGMENTS 
WHERE SEGMENT_NAME = 'SALES';

SEGMENT_NA BYTES_NOT_POPULATED POPULATE_STAT
---------- ------------------- -------------
SALES                        0 COMPLETED

-- 4.3 查看内存使用情况
SELECT POOL, ALLOC_BYTES, USED_BYTES FROM V$INMEMORY_AREA;
POOL                       ALLOC_BYTES USED_BYTES
-------------------------- ----------- ----------
1MB POOL                    3001024512  294649856
64KB POOL                   1275068416    3604480

5. 性能测试比较
5.1 禁用In-Memory时的查询性能
-- 临时禁用In-Memory
ALTER TABLE sales NO INMEMORY;

-- 执行查询并记录时间
SET TIMING ON
SET AUTOTRACE TRACE STATISTICS

-- 查询1:按区域汇总销售额
SELECT region, SUM(amount) 
FROM sales 
GROUP BY region;

9 rows selected.

Elapsed: 00:00:02.94

Statistics
----------------------------------------------------------
140  recursive calls
11  db block gets
53396  consistent gets
53196  physical reads
1944  redo size
854  bytes sent via SQL*Net to client
415  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
20  sorts (memory)
0  sorts (disk)
9  rows processed

-- 查询2:按产品和日期范围汇总
SELECT product_id, 
TO_CHAR(sale_date, 'YYYY-MM'), 
SUM(quantity), 
SUM(amount)
FROM sales
WHERE sale_date BETWEEN TO_DATE('2023-01-01', 'YYYY-MM-DD') 
AND TO_DATE('2023-12-31', 'YYYY-MM-DD')
GROUP BY product_id, TO_CHAR(sale_date, 'YYYY-MM')
ORDER BY product_id, TO_CHAR(sale_date, 'YYYY-MM');

12000 rows selected.

Elapsed: 00:00:03.14

Statistics
----------------------------------------------------------
9  recursive calls
20  db block gets
53222  consistent gets
53194  physical reads
3868  redo size
430985  bytes sent via SQL*Net to client
9489  bytes received via SQL*Net from client
801  SQL*Net roundtrips to/from client
1  sorts (memory)
0  sorts (disk)
12000  rows processed

SET TIMING OFF
SET AUTOTRACE OFF

5.2 启用In-Memory时的查询性能
-- 重新启用In-Memory
ALTER TABLE sales INMEMORY;

-- 确保数据已加载
SELECT /*+ FULL(sales) NO_PARALLEL(sales) */ COUNT(*) FROM sales;

SELECT SEGMENT_NAME, BYTES_NOT_POPULATED, POPULATE_STATUS 
FROM V$IM_SEGMENTS 
WHERE SEGMENT_NAME = 'SALES';

-- 执行相同的查询并记录时间
SET TIMING ON
SET AUTOTRACE TRACE STATISTICS

-- 查询1:按区域汇总销售额
SELECT region, SUM(amount) 
FROM sales 
GROUP BY region;


9 rows selected.

Elapsed: 00:00:00.54

Statistics
----------------------------------------------------------
1  recursive calls
0  db block gets
9  consistent gets
0  physical reads      <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
0  redo size
854  bytes sent via SQL*Net to client
415  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
9  rows processed


-- 查询2:按产品和日期范围汇总
SELECT product_id, 
TO_CHAR(sale_date, 'YYYY-MM'), 
SUM(quantity), 
SUM(amount)
FROM sales
WHERE sale_date BETWEEN TO_DATE('2023-01-01', 'YYYY-MM-DD') 
AND TO_DATE('2023-12-31', 'YYYY-MM-DD')
GROUP BY product_id, TO_CHAR(sale_date, 'YYYY-MM')
ORDER BY product_id, TO_CHAR(sale_date, 'YYYY-MM');

12000 rows selected.

Elapsed: 00:00:01.15

Statistics
----------------------------------------------------------
1  recursive calls
0  db block gets
9  consistent gets
0  physical reads
0  redo size
430985  bytes sent via SQL*Net to client
9489  bytes received via SQL*Net from client
801  SQL*Net roundtrips to/from client
1  sorts (memory)
0  sorts (disk)
12000  rows processed

SET TIMING OFF
SET AUTOTRACE OFF

5.3 验证执行计划
-- 验证查询是否使用了In-Memory
EXPLAIN PLAN FOR 
SELECT region, SUM(amount) FROM sales GROUP BY region;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

Plan hash value: 2895541888

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     9 |   117 |   712  (23)| 00:00:01 |
|   1 |  HASH GROUP BY              |       |     9 |   117 |   712  (23)| 00:00:01 |
|   2 |   TABLE ACCESS INMEMORY FULL| SALES |    10M|   123M|   711  (23)| 00:00:01 |
-------------------------------------------------------------------------------------

EXPLAIN PLAN FOR
SELECT product_id, 
TO_CHAR(sale_date, 'YYYY-MM'), 
SUM(quantity), 
SUM(amount)
FROM sales
WHERE sale_date BETWEEN TO_DATE('2023-01-01', 'YYYY-MM-DD') 
AND TO_DATE('2023-12-31', 'YYYY-MM-DD')
GROUP BY product_id, TO_CHAR(sale_date, 'YYYY-MM')
ORDER BY product_id, TO_CHAR(sale_date, 'YYYY-MM');
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

Plan hash value: 3229864837

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |   257K|  5027K|       |  7395   (8)| 00:00:01 |
|   1 |  SORT GROUP BY              |       |   257K|  5027K|    76M|  7395   (8)| 00:00:01 |
|*  2 |   TABLE ACCESS INMEMORY FULL| SALES |  2494K|    47M|       |   911  (40)| 00:00:01 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - inmemory("SALE_DATE">=TO_DATE(' 2023-01-01 00:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "SALE_DATE"<=TO_DATE(' 2023-12-31 00:00:00', 'syyyy-mm-dd
hh24:mi:ss'))
filter("SALE_DATE">=TO_DATE(' 2023-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')
AND "SALE_DATE"<=TO_DATE(' 2023-12-31 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

18 rows selected.

6. 自动In-Memory管理(AIM) 说明
-- 6.1 启用AIM
ALTER SYSTEM SET INMEMORY_AUTOMATIC_LEVEL = ADVANCED;

--OFF, HIGH, MEDIUM, LOW

1. 自动管理 In-Memory 对象的生命周期
自动加载/卸载: AIM 会根据 SQL 查询的访问频率,自动将频繁访问的表/列加载到 In-Memory Column Store,并淘汰不常用的数据。
动态优先级调整: 自动调整 INMEMORY_PRIORITY(如将热点数据设为 HIGH,冷数据设为 LOW)。
2. 优化内存利用率
智能内存分配: 在 INMEMORY_SIZE 有限的情况下,AIM 会优先保留高价值数据,避免内存浪费。
自动压缩策略: 根据访问模式动态选择压缩级别(如 FOR QUERY LOW 或 FOR CAPACITY HIGH)。
3. 减少手动干预
无需手动指定 INMEMORY 属性,AIM 会自动识别适合列式存储的对象。

可选参数:
--OFF, HIGH, MEDIUM, LOW

LOW:当Inmemory内存存在压力时,数据库将从IM列存储中清除冷数据。
MEDIUM:当Inmemory内存存在压力时,能保证任何热数据不被首先清除出去。
OFF:这是默认值。当设置此值时,将禁用自动内存功能。

在19c中一键搞定
INMEMORY_AUTOMATIC_LEVEL增加了一个新的值HIGH,我们只需设置一个大小,设置一个级别HIGH,就全搞定了。

7. 测试不同压缩级别的影响
-- 7.1 更改压缩级别为MEMCOMPRESS FOR CAPACITY HIGH
ALTER TABLE sales INMEMORY MEMCOMPRESS FOR CAPACITY HIGH;

-- 重新加载数据
SELECT /*+ FULL(sales) NO_PARALLEL(sales) */ COUNT(*) FROM sales;

-- 7.2 检查内存使用变化
SELECT POOL, ALLOC_BYTES, USED_BYTES 
FROM V$INMEMORY_AREA;

SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY 
FROM DBA_TABLES 
WHERE TABLE_NAME = 'SALES';


CAPACITY HIGH:(ALTER TABLE sales INMEMORY MEMCOMPRESS FOR CAPACITY HIGH;)
POOL                       ALLOC_BYTES USED_BYTES
-------------------------- ----------- ----------
1MB POOL                    3001024512   74448896 <<<<<<<<<<<<<<<<<<<
64KB POOL                   1275068416    3604480

FOR QUERY LOW:(ALTER TABLE sales INMEMORY MEMCOMPRESS FOR QUERY LOW;)
POOL                       ALLOC_BYTES USED_BYTES
-------------------------- ----------- ----------
1MB POOL                    3001024512  294649856 <<<<<<<<<<<<<<<<<<<
64KB POOL                   1275068416    3604480

NO MEMCOMPRESS:(ALTER TABLE sales INMEMORY NO MEMCOMPRESS;)
POOL                       ALLOC_BYTES USED_BYTES
-------------------------- ----------- ----------
1MB POOL                    3001024512  415236096 <<<<<<<<<<<<<<<<<<<
64KB POOL                   1275068416   19333120

说明:CAPACITY HIGH 74M左右;FOR QUERY LOW 294M左右;NO MEMCOMPRESS 415M左右;最高压缩和不压缩相差6倍左右。

===============================================================================================
其他:

- 清理缓冲区缓存
ALTER SYSTEM FLUSH BUFFER_CACHE;

-- 清理共享池
ALTER SYSTEM FLUSH SHARED_POOL;

==========================================================================================================================
单列缓存测试:

ALTER TABLE sales INMEMORY MEMCOMPRESS FOR QUERY LOW;


ALTER TABLE sales INMEMORY MEMCOMPRESS FOR QUERY LOW (amount) NO INMEMORY (sale_id, product_id, sale_date, quantity, region);

SELECT /*+ FULL(sales) NO_PARALLEL(sales) */ COUNT(*) FROM sales;

SELECT POOL, ALLOC_BYTES, USED_BYTES 
FROM V$INMEMORY_AREA;

-- 确认只有amount列被加载
SELECT segment_name, bytes_not_populated 
FROM v$im_segments 
WHERE segment_name = 'SALES';

-- 检查列压缩状态
col owner for a10
col TABLE_NAME for a10
col COLUMN_NAME for a22
select * from v$im_column_level where TABLE_NAME= 'SALES';


EXPLAIN PLAN FOR 
SELECT SUM(amount) FROM sales;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

EXPLAIN PLAN FOR 
SELECT SUM(quantity) FROM sales;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

http://www.lryc.cn/news/613230.html

相关文章:

  • Renesas Electronics RA8M1语音套件(VK-RA8M1)
  • 深入解析Go设计模式:责任链模式实战
  • Electron 中 license-keys 的完整集成方案
  • 网络虚拟化是啥啊?
  • 自然语言处理×第四卷:文本特征与数据——她开始准备:每一次输入,都是为了更像你地说话
  • 拥抱云原生:从传统架构到云原生架构的演进与实践
  • python题目练习 无重叠区间
  • 京东关键字搜索商品列表接口开发实战:从参数优化到分布式调用
  • yolo目标检测技术:基础概念(一)
  • 【洛谷题单】--分支结构(一)
  • 脱机部署k3s
  • Python 常用内置高阶函数
  • OO SALV的栏位功能
  • 大屏数据展示页面,数据可视化可以用到的框架和插件
  • 阿里云部署若依后,浏览器能正常访问,但是apifox和小程序访问后报错链接被重置
  • day27 同步互斥
  • IDEA-Research推出的一系列检测、分割模型:从DINO(改进版DETR)、Grounding Dino、DINO-X到Grounded SAM2
  • 【SPIE出版| 前4届均已完成EI检索】第五届算法、高性能计算与人工智能国际学术会议(AHPCAI 2025)
  • 解决GitHub push失败-Failed to connect to github.com port 443: Timed out
  • YooAsset为什么要分组
  • 《深入Java包装类体系:类型转换原理与Integer缓存实战指南》
  • jetson上使用opencv的gstreamer进行MIPI和USB摄像头的连接以及udp推流
  • PyTorch RNN 名字分类器
  • 解决 npm i node-sass@4.12.0 安装失败异常 npm i node-sass异常解决
  • QT的拖拽功能
  • vue-plugin-hiprint 打印模版使用
  • DicomObjects COM 8.XX
  • 云平台运维工具 ——AWS 原生工具
  • 008 前端vue
  • 解决React白板应用中的画布内容丢失问题