找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 272|回复: 11

Oracle亿行数据秒查询-即行存转内存列存inmemory

[复制链接]
发表于 昨天 09:38 | 显示全部楼层 |阅读模式
本帖最后由 likeyouli 于 2026-9-21 11:37 编辑

最近用了一下duckdb+parquet,深刻感受到列存的巨大速度优势,原来8千多万行数据、20多GB的表,在Oracle数据库来一个count(*)就得好几分钟,但用parquet秒出结果。
于是乎感慨Oracle这么有名的数据库,难道查询就做的这么差?经过研究发现,行存对于增删改有天然优势,对于查询则没有列存有优势;反之列存对于增删改也是巨麻烦。
         难道不能两全其美?
Oracle也考虑到了,只不过是行存转内存列存,需要一定的内存。闲话不说了,开干(我用的26ai版本,其他版本不清楚):
在执行下边命令之前,先看看自己的sga空间够不够:
SQL> SHOW PARAMETER sga_target;
SQL> SHOW PARAMETER sga_max_size;
顺便看一下pga:SQL> SHOW PARAMETER pga_aggregate_target;


附上几个调整的命令(具体数字自己更改):
-- 动态调整 PGA(通常立即生效)
ALTER SYSTEM SET pga_aggregate_target = 1G;

-- 动态调整 SGA_TARGET(前提是目标值 ≤ SGA_MAX_SIZE)
ALTER SYSTEM SET sga_target = 2G;

-- 如果需要调大 SGA_MAX_SIZE,则必须使用 SCOPE=SPFILE 并重启
ALTER SYSTEM SET sga_max_size = 3G SCOPE=SPFILE;
下边开始设置inmemory:
SQL> ALTER SYSTEM SET INMEMORY_FORCE = BASE_LEVEL SCOPE = SPFILE;
System altered.
SQL> ALTER SYSTEM SET INMEMORY_SIZE = 2G SCOPE = SPFILE;  (这里最大能免费开到16G,注意这里的空间是从sga里分出来的,所以sga必须大,否则数据库就启动不了)
System altered.
SQL> ALTER SYSTEM SET INMEMORY_AUTOMATIC_LEVEL = MEDIUM SCOPE = BOTH;
System altered.

查询一下看看有没有成功:
select e.*,listagg(used_bytes,',')within group (order by used_bytes) over(partition by null) as lianjie,
(sum(used_bytes) over(partition by null))/1024/1024 as "已用空间(MB)",(sum(alloc_bytes) over(partition by null))/1024/1024 as "总空间(MB)",
(alloc_bytes-used_bytes)/1024/1024 as "各个池剩余空间" from v$inmemory_area e ;
    这里的总空间就是你刚才设置的inmemory, 1MB POOL 没有剩余空间将会提示内存不足。

因为这个26列8千万的表,占空间20多gb,我因物理内存涨价太厉害,只给inmemory开了2g,远放不下整个表,所以开始的时候研究Oracle官网:https://docs.oracle.com/en/datab ... 8-B3EE-6FDAB6E23E2E
ALTER TABLE oe.product_information  
   INMEMORY MEMCOMPRESS FOR QUERY (
      product_id, product_name, category_id, supplier_id, min_price)
   INMEMORY MEMCOMPRESS FOR CAPACITY HIGH (
      product_description, warranty_period, product_status, list_price)
   NO INMEMORY (
      weight_class, catalog_url);
根据上述命令,我哪怕仅设置一列,仍提示内存不足。

最后我想到里用此办法,完美装进10了列:
                create table test_neicun2 inmemory memcompress for capacity high as select jshid,yybm,yymc,yyxmmc,ybxmmc,zje,tcje,fyfssj from yb_fymx_ws;
                ALTER TABLE test_neicun2 INMEMORY PRIORITY HIGH memcompress for capacity high;
                完美实现数据秒查询。
  附上常用命令:
SQL> alter system set inmemory_size=2260m scope=both;   这样连接数据库执行的sqlplus /  as sysdba;
EXEC DBMS_INMEMORY.POPULATE('LIKEYOU32', 'TEST_NEICUN');  手动触发填充进内存,这里的likeyou32为你的用户名,TEST_NEICUN为你的实际表名字

又从官网找到了INMEMORY_FORCE的BASE_LEVEL参数含义:https://docs.oracle.com/en/datab ... E-8AE0-BD7922B239BE
免费但有上限:它的目的是让你在不购买 In-Memory 选件的情况下,可以使用 最多 16GB 的列存储来进行测试和评估。你之前在 8GB 物理内存上折腾 2GB 的 INMEMORY_SIZE,就是在这个框架内。

压缩级别被锁定:无论你在建表或改表时写了什么压缩级别,系统都会自动、透明地强制使用 QUERY LOW 压缩。这其实解释了为什么你之前尝试 MEMCOMPRESS FOR CAPACITY HIGH 时,v$im_column_level 里显示的仍然是 DEFAULT,因为 BASE_LEVEL 模式覆盖了你的手动设置。

原来我用那些命令压缩都没生效,没办法,免费的只能这样。
内存列存相关查询及其含义解释:https://docs.oracle.com/en/datab ... -INMEMORY_AREA.html  


发表于 昨天 10:35 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

发表于 昨天 12:10 | 显示全部楼层
技术文章怎么发休闲娱乐中来了
回复

使用道具 举报

发表于 昨天 13:16 | 显示全部楼层
看楼主的文章,学习一下啊
回复

使用道具 举报

发表于 昨天 14:24 | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 昨天 16:22 | 显示全部楼层
Oracle亿行数据秒查询-即行存转内存列存inmemory 不错
回复

使用道具 举报

发表于 昨天 16:28 | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 昨天 18:27 | 显示全部楼层
支持一下,内容很实用。
回复

使用道具 举报

发表于 14 小时前 | 显示全部楼层
回复

使用道具 举报

发表于 13 小时前 来自手机 | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 11 小时前 | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 9 小时前 | 显示全部楼层
感谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1|闽公网安备35020302032614号 )

GMT+8, 2026-9-22 20:46

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表