如何解决在数据仓库中保存大列数据的最佳方法
我有一个表,用于存储对事务的更改。所有更改都被捕获到一个表中。作为事务一部分的列之一可以具有许多逗号分隔的值。无法预测发生的次数。另外,该字段不是必填字段,也可以具有空值。
我在表中进行的交易总数约为1亿次。在这些记录中,为其填充值的记录数为1M。在1M个事务中,记录长度超过4000个的记录数约为〜37K。
我提到的长度为4000,因为在我的oracle表中将保存该长度的列定义为varchar2(4000)。
我到处检查,发现如果必须保存长度未知的内容,则应将表列数据类型定义为clob。但是clob对我来说是昂贵的,因为只有极少量的数据具有> 4000的长度。如果我雪花执行星型模式并创建另一个表来存储值,那么即使我的事务长度小于4000,保存为clob列的一部分。在存储和性能上这都是昂贵的。
有人可以建议我解决这个问题的方法吗?
谢谢 S
解决方法
您可以创建一个主详细信息表来存储逗号分隔的值,然后可以有行,而不是将所有逗号分隔的值保存在单个列中。可以使用主表和明细表之间的伪密钥,通过前向密钥来管理此问题。
,这是一个选择。
创建两列,例如
create table storage
(id number primary key,long_text_1 varchar2(4000),long_text_2 varchar2(4000)
);
存储类似值
insert into storage (id,long_text_1,long_text_2)
values (seq.nextval,substr(input_value,1,4000),4001,4000)
);
从表中检索它们时,将它们连接起来:
select id,long_text_1 || long_text_2 as long_text
from storage
where ...
,
您可能会受益于使用内联SecurFile CLOB。使用内联CLOB,像常规VARCHAR2这样的行中最多可以存储约4000字节的数据,并且只有较大的值才能存储在单独的CLOB段中。借助SecureFiles,Oracle可以显着提高CLOB性能。 (例如,SecureFiles的导入和导出比老式的BasicFile LOB格式要快得多。)
取决于您的版本,参数和表DDL,您的数据库可能已经将CLOB存储为内联SecureFiles。确保您的COMPATIBLE设置为11.2或更高,并且DB_SECUREFILE是“允许”,“始终”或“首选”之一:
select name,value from v$parameter where name in ('compatible','db_securefile') order by 1;
使用这样的查询来确保正确设置了表,并且没有人覆盖系统设置:
select dbms_metadata.get_ddl('TABLE','YOUR_TABLE_NAME') from dual;
您应该在结果中看到以下内容:
... LOB ("CLOB_NAME") STORE AS SECUREFILE (... ENABLE STORAGE IN ROW ...) ...
CLOB的主要问题之一是它们存储在单独的段中,并且必须遍历LOB索引才能将表中的每一行映射到另一段中的值。下面的演示创建了两个表,以表明当数据较小且以内联方式存储时,不需要使用LOB段。
--drop table clob_test_inline;
--drop table clob_test_not_in;
create table clob_test_inline(a number,b clob) lob(b) store as securefile (enable storage in row);
create table clob_test_not_in(a number,b clob) lob(b) store as (disable storage in row);
insert into clob_test_inline select level,lpad('A',900,'A') from dual connect by level <= 10000;
insert into clob_test_not_in select level,'A') from dual connect by level <= 10000;
commit;
内联表段很大,因为它保存所有数据。离线表段很小,因为其所有数据都保存在其他位置。
select segment_name,bytes/1024/1024 mb_inline
from dba_segments
where segment_name like 'CLOB_TEST%'
order by 1;
SEGMENT_NAME MB_INLINE
---------------- ---------
CLOB_TEST_INLINE 27
CLOB_TEST_NOT_IN 0.625
查看LOB段,大小反转。内联表不在LOB段中存储任何内容。
select table_name,bytes/1024/1024 mb_out_of_line
from dba_segments
join dba_lobs
on dba_segments.owner = dba_lobs.owner
and dba_segments.segment_name = dba_lobs.segment_name
where dba_lobs.table_name like 'CLOB_TEST%'
order by 1;
TABLE_NAME MB_OUT_OF_LINE
------------ --------------
CLOB_TEST_INLINE 0.125
CLOB_TEST_NOT_IN 88.1875
尽管有上述情况,但我不能保证CLOB仍然可以为您工作。我只能说值得使用CLOB测试数据。您仍然需要注意一些事项。 CLOB存储文本的方式略有不同(UCS2而不是UTF8),这可能会占用更多空间,具体取决于您的字符集。因此,请检查分段大小。但也要注意,段大小较小时可能会撒谎-样本数据有很多自动分配的开销,因此您在测试时要使用实际大小。
最后,正如劳尔指出的那样,将非原子值存储在一个字段中通常是一个可怕的错误。也就是说,在极少数情况下,数据仓库需要打破性能规则,并且数据必须尽可能紧凑地存储。在以这种方式存储数据之前,请确保您永远不需要基于这些值进行联接或查询单个值。如果您认为处理100M行很困难,请等到尝试拆分100M值,然后将它们连接到另一个表时。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。