ITPub博客

首页 > 数据库 > Oracle > [20140109]sqlldr使用direct=true加载数据的问题.txt

[20140109]sqlldr使用direct=true加载数据的问题.txt

Oracle 作者:xiaoyan5686670 时间:2016-08-17 16:11:03 0 删除 编辑
[20140109]sqlldr使用direct=true加载数据的问题.txt

昨天要同步更新一个数据库的信息,我仅仅负责取出数据给别人加载,我使用toad带的save菜单可以自动生产sqlldr的导入参数文件以及数据.
自己以前从来没有做过.结果我使用参数direct=true,因为有重复数据存在,导致正常的索引失效.好在表不是太大,对业务影响不大,自己做
一个例子测试看看.

1.建立测试环境:
SCOTT@test> @ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

拿scott.dept表为模板建立测试表depta:

create table scott.depta as select * from dept where deptno=10;
create unique index pk_depta on depta (deptno);
alter table scott.depta add ( constraint pk_depta primary key (deptno)  using index pk_depta  enable validate);

--建立sqlldr加载文件,在toad下很简单,选择export format为sql loader就ok,生成脚本如下:

内容如下:
-- SQL Loader Control and Data File created by TOAD
-- Variable length, terminated enclosed data formatting
--
-- The format for executing this file with SQL Loader is:
-- SQLLDR control=<filename> Be sure to substitute your
-- version of SQL LOADER and the filename for this file.
--
-- Note: Nested table datatypes are not supported here and
--       will be exported as nulls.
LOAD DATA
INFILE *
BADFILE './c.BAD'
DISCARDFILE './c.DSC'
APPEND INTO TABLE SCOTT.DEPTA
Fields terminated by ";" Optionally enclosed by '"'
(
  DEPTNO NULLIF (DEPTNO="NULL"),
  DNAME,
  LOC
)
BEGINDATA
10;"ACCOUNTING";"NEW YORK"
20;"RESEARCH";"DALLAS"
30;"SALES";"CHICAGO"
40;"OPERATIONS";"BOSTON"

2.使用sqlldr导入:
$ sqlldr
SQL*Loader: Release 11.2.0.3.0 - Production on Thu Jan 9 11:18:38 2014
Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
Usage: SQLLDR keyword=value [,keyword=value,...]
Valid Keywords:

    userid -- ORACLE username/password
   control -- control file name
       log -- log file name
       bad -- bad file name
      data -- data file name
   discard -- discard file name
discardmax -- number of discards to allow          (Default all)
      skip -- number of logical records to skip    (Default 0)
      load -- number of logical records to load    (Default all)
    errors -- number of errors to allow            (Default 50)
      rows -- number of rows in conventional path bind array or between direct path data saves
               (Default: Conventional path 64, Direct path all)
  bindsize -- size of conventional path bind array in bytes  (Default 256000)
    silent -- suppress messages during run (header,feedback,errors,discards,partitions)
    direct -- use direct path                      (Default FALSE)
   parfile -- parameter file: name of file that contains parameter specifications
  parallel -- do parallel load                     (Default FALSE)
      file -- file to allocate extents from
skip_unusable_indexes -- disallow/allow unusable indexes or index partitions  (Default FALSE)
skip_index_maintenance -- do not maintain indexes, mark affected indexes as unusable  (Default FALSE)
commit_discontinued -- commit loaded rows when load is discontinued  (Default FALSE)
  readsize -- size of read buffer                  (Default 1048576)
external_table -- use external table for load; NOT_USED, GENERATE_ONLY, EXECUTE  (Default NOT_USED)
columnarrayrows -- number of rows for direct path column array  (Default 5000)
streamsize -- size of direct path stream buffer in bytes  (Default 256000)
multithreading -- use multithreading in direct path
 resumable -- enable or disable resumable for current session  (Default FALSE)
resumable_name -- text string to help identify resumable statement
resumable_timeout -- wait time (in seconds) for RESUMABLE  (Default 7200)
date_cache -- size (in entries) of date conversion cache  (Default 1000)
no_index_errors -- abort load on any index errors  (Default FALSE)

PLEASE NOTE: Command-line parameters may be specified either by
position or by keywords.  An example of the former case is 'sqlldr
scott/tiger foo'; an example of the latter is 'sqlldr control=foo
userid=scott/tiger'.  One may specify parameters by position before
but not after parameters specified by keywords.  For example,
'sqlldr scott/tiger control=foo logfile=log' is allowed, but
'sqlldr scott/tiger control=foo log' is not, even though the
position of the parameter 'log' is correct.

--direct -- use direct path                      (Default FALSE)

$ sqlldr scott/xxxx control=c.ctl direct=true
SQL*Loader: Release 12.1.0.1.0 - Production on Thu Jan 9 10:54:57 2014
Copyright (c) 1982, 2013, Oracle and/or its affiliates.  All rights reserved.
Path used:      Direct
Load completed - logical record count 4.
Table SCOTT.DEPTA:
4 Rows successfully loaded.
Check the log file:
  c.log
for more information about the load.

SCOTT@test> select rowid,depta.* from depta ;
ROWID                  DEPTNO DNAME          LOC
------------------ ---------- -------------- -------------
AABEz4AAEAAAAIjAAA         10 ACCOUNTING     NEW YORK
AABEz4AAEAAAAIkAAA         10 ACCOUNTING     NEW YORK
AABEz4AAEAAAAIkAAB         20 RESEARCH       DALLAS
AABEz4AAEAAAAIkAAC         30 SALES          CHICAGO
AABEz4AAEAAAAIkAAD         40 OPERATIONS     BOSTON

--哦!发现导入成功!,但是数据的唯一性破坏了.

SCOTT@test> select index_name,STATUS from user_indexes where  table_name='DEPTA';
INDEX_NAME                     STATUS
------------------------------ --------
PK_DEPTA                       UNUSABLE

--索引失效.导致执行计划改变.

SCOTT@test> select * from depta where deptno=10;
    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        10 ACCOUNTING     NEW YORK

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
------------------------------------------------------------
SQL_ID  6bxpvjvct2nc5, child number 0
-------------------------------------
select * from depta where deptno=10
Plan hash value: 4292077131
---------------------------------------------------------
| Id  | Operation         | Name  | E-Rows | Cost (%CPU)|
---------------------------------------------------------
|   0 | SELECT STATEMENT  |       |        |     3 (100)|
|*  1 |  TABLE ACCESS FULL| DEPTA |      4 |     3   (0)|
---------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("DEPTNO"=10)

SCOTT@test> delete /*+ full(depta) */ from depta where rowid='AABEz4AAEAAAAIkAAA';
delete /*+ full(depta) */ from depta where rowid='AABEz4AAEAAAAIkAAA'
*
ERROR at line 1:
ORA-01502: index 'SCOTT.PK_DEPTA' or partition of such index is in unusable state

SCOTT@test> @hide skip_unusable_indexes
old  10:  and lower(a.ksppinm) like lower('%&1%')
new  10:  and lower(a.ksppinm) like lower('%skip_unusable_indexes%')
NAME                   DESCRIPTION                           DEFAULT_VALUE          SESSION_VALUE          SYSTEM_VALUE
---------------------- ------------------------------------- ---------------------- ---------------------- ----------------------
skip_unusable_indexes  skip unusable indexes if set to TRUE  TRUE                   TRUE                   TRUE

SCOTT@test> set serveroutput on
SCOTT@test> exec print_table('select * from user_CONSTRAINTS where constraint_name=''PK_DEPTA''');
OWNER                         : SCOTT
CONSTRAINT_NAME               : PK_DEPTA
CONSTRAINT_TYPE               : P
TABLE_NAME                    : DEPTA
SEARCH_CONDITION              :
R_OWNER                       :
R_CONSTRAINT_NAME             :
DELETE_RULE                   :
STATUS                        : ENABLED
DEFERRABLE                    : NOT DEFERRABLE
DEFERRED                      : IMMEDIATE
VALIDATED                     : VALIDATED
GENERATED                     : USER NAME
BAD                           :
RELY                          :
LAST_CHANGE                   : 2014-01-09 10:45:43
INDEX_OWNER                   : SCOTT
INDEX_NAME                    : PK_DEPTA
INVALID                       :
VIEW_RELATED                  :
-----------------

PL/SQL procedure successfully completed.

--约束还是enabled的.我采用的disable约束,再删除重复记录.

3.解决方法:
SCOTT@test> alter table depta modify constraint pk_depta  disable;
Table altered.

SCOTT@test> delete /*+ full(depta) */ from depta where rowid='AABEz4AAEAAAAIkAAA';
delete /*+ full(depta) */ from depta where rowid='AABEz4AAEAAAAIkAAA'
*
ERROR at line 1:
ORA-01502: index 'SCOTT.PK_DEPTA' or partition of such index is in unusable state
--依旧不行.可能我是先建立索引,再建立约束的原因,这样索引不会删除.

SCOTT@test> drop index pk_depta ;
Index dropped.

SCOTT@test> delete  from depta where rowid='AABEz4AAEAAAAIkAAA';
1 row deleted.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter table depta modify constraint pk_depta  enable;
Table altered.

SCOTT@test> select index_name,STATUS from user_indexes where  table_name='DEPTA';
INDEX_NAME                     STATUS
------------------------------ --------
PK_DEPTA                       VALID


SCOTT@test> select * from depta where deptno=10;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
SQL_ID  6bxpvjvct2nc5, child number 0
-------------------------------------
select * from depta where deptno=10

Plan hash value: 2411761151

----------------------------------------------------------------------
| Id  | Operation                   | Name     | E-Rows | Cost (%CPU)|
----------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |        |     1 (100)|
|   1 |  TABLE ACCESS BY INDEX ROWID| DEPTA    |      1 |     1   (0)|
|*  2 |   INDEX UNIQUE SCAN         | PK_DEPTA |      1 |     0   (0)|
----------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("DEPTNO"=10)

总结:
1.使用sqlldr确实应该注意这个参数direct=true.
2.这次好在表不是太大,否则后果很严重,对生产系统影响不大.总之年关做事还是小心为上.

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22569416/viewspace-2123626/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2012-07-25

  • 博文量
    108
  • 访问量
    198834