任何人都可以通过ORACLE_LOADER
访问驱动程序解释以下两个使用Oracle外部表性能改进的声明:
用代码解释可能有助于我深入理解这个概念。这是两个语法:
固定字段长度
create table ext_table_fixed (
field_1 char(4),
field_2 char(30)
)
organization external (
type oracle_loader
default directory ext_dir
access parameters (
records delimited by newline
fields (
field_1 position(1: 4) char( 4),
field_2 position(5:30) char(30)
)
)
location ('file')
)
reject limit unlimited;
逗号分隔
create table ext_table_csv (
i Number,
n Varchar2(20),
m Varchar2(20)
)
organization external (
type oracle_loader
default directory ext_dir
access parameters (
records delimited by newline
fields terminated by ','
missing field values are null
)
location ('file.csv')
)
reject limit unlimited;
答案 0 :(得分:4)
简化,概念性,非数据库特定的解释:
当预先知道最大可能记录长度时,可以在恒定时间内找到记录的结尾/下一记录的开头。这是因为该位置可以使用简单的加法来计算,非常类似于数组索引。想象一下,我使用int
作为记录的指针,并且记录大小是在某处定义的整数常量。然后,从当前记录位置到下一个:
int current_record = /* whatever */;
int next_record = current_record + FIXED_RECORD_SIZE;
就是这样!
或者,当使用字符串终止(或以其他方式分隔)的记录和字段时,您可以想象通过线性时间扫描找到下一个字段/记录,该扫描必须查找每个字符,直到找到分隔符。和以前一样,
char DELIMITER = ','; // or whatever
int current_record = /* whatever */;
int next_record = current_record;
while(character_at_location(next_record) != DELIMITER) {
next_record++;
}
这可能是现实世界实现的简化或天真版本,但总体思路仍然存在:你不能轻易地在恒定时间内做同样的操作,即使它是恒定的时间,它也不可能是与执行单个添加操作一样快。
答案 1 :(得分:0)
我检查了这个,在我的情况下性能恶化了!我有一个带有整数值的1GB csv文件,每个文件长度为10个字符,填充,字段用","和记录用" \ n"分隔。我必须遵循脚本(我也尝试设置固定的记录大小并删除ltrim,但它没有帮助)。
SQL> CREATE TABLE ints_ext (id0 NUMBER(10),
2 id1 NUMBER(10),
3 id2 NUMBER(10),
4 id3 NUMBER(10),
5 id4 NUMBER(10),
6 id5 NUMBER(10),
7 id6 NUMBER(10),
8 id7 NUMBER(10),
9 id8 NUMBER(10),
10 id9 NUMBER(10))
11 ORGANIZATION EXTERNAL (
12 TYPE oracle_loader
13 DEFAULT DIRECTORY tpch_dir
14 ACCESS PARAMETERS (
15 RECORDS DELIMITED BY NEWLINE
16 BADFILE 'bad_%a_%p.bad'
17 LOGFILE 'log_%a_%p.log'
18 FIELDS TERMINATED BY ','
19 MISSING FIELD VALUES ARE NULL)
20 LOCATION ('data1_1.csv'))
21 parallel 1
22 REJECT LIMIT 0
23 NOMONITORING;
SQL> select count(*) from ints_ext;
COUNT(*)
----------
9761289
Elapsed: 00:00:43.68
SQL> select /*+ parallel(1) tracing(STRIP,1) */ * from ints_ext;
no rows selected
Elapsed: 00:00:43.78
SQL> CREATE TABLE ints_ext (id0 NUMBER(10),
2 id1 NUMBER(10),
3 id2 NUMBER(10),
4 id3 NUMBER(10),
5 id4 NUMBER(10),
6 id5 NUMBER(10),
7 id6 NUMBER(10),
8 id7 NUMBER(10),
9 id8 NUMBER(10),
10 id9 NUMBER(10))
11 ORGANIZATION EXTERNAL (
12 TYPE oracle_loader
13 DEFAULT DIRECTORY tpch_dir
14 ACCESS PARAMETERS (
15 RECORDS DELIMITED BY NEWLINE
16 BADFILE 'bad_%a_%p.bad'
17 LOGFILE 'log_%a_%p.log'
18 FIELDS ltrim (
19 id0 position(1:10) char(10),
20 id1 position(12:21) char(10),
21 id2 position(23:32) char(10),
22 id3 position(34:43) char(10),
23 id4 position(45:54) char(10),
24 id5 position(56:65) char(10),
25 id6 position(67:76) char(10),
26 id7 position(78:87) char(10),
27 id8 position(89:98) char(10),
28 id9 position(100:109) char(10)
29 ))
30 LOCATION ('data1_1.csv'))
31 parallel 1
32 REJECT LIMIT 0
33 NOMONITORING;
SQL> select count(*) from ints_ext;
COUNT(*)
----------
9761289
Elapsed: 00:00:50.38
SQL>
select /*+ parallel(1) tracing(STRIP,1) */ * from ints_ext;
no rows selected
Elapsed: 00:00:45.26