|
|
本帖最后由 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-6FDAB6E23E2EALTER 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
|
|