2

任何人都可以解释以下两个语句 wrt 使用ORACLE_LOADER访问驱动程序改进 Oracle 外部表性能:

  1. 固定长度记录的处理速度比以字符串结尾的记录要快。
  2. 固定长度字段的处理速度比分隔字段快。

用代码解释可能有助于我深入理解这个概念。这是两种语法:

固定字段长度

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;
4

2 回答 2

4

简化的、概念性的、非数据库特定的解释:

当预先知道最大可能的记录长度时,可以在恒定时间内找到记录的结尾/下一条记录的开头。这是因为该位置可以使用简单的加法计算,非常类似于数组索引。想象一下,我使用ints 作为指向记录的指针,并且记录大小是在某处定义的整数常量。然后,从当前记录位置获取到下一个:

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++;
}

这可能是现实世界实现的简化或幼稚版本,但总体思路仍然存在:您不能轻易地在恒定时间内完成相同的操作,即使是恒定时间,也不太可能像执行单个添加操作。

于 2013-01-26T15:33:07.807 回答
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
于 2015-02-10T21:01:20.107 回答