オラクルデータ移行方法のまとめ

オラクルデータ移行方法の概要

データベースはデータをメンテナスするシステムシステムだから、当然データの移行、いわゆる投入と抽出は非常に重要かつ頻繁である。
オラクルデータベースは多様なデータメンテナンス方法を提供していて、データ移行業務に使える手法は七種類ほどある。普通は戸惑うんであろう。
それぞれの手法は特徴があって、一律にいい、わるいとはいいきれないが、敢えてよく問われる効率性、安全性の面から、実務とあわせて整理してみたいと思う。

結論からいうと

  • 一般的な処理、最も効率的なデータ移行方法はCREATE TABLE AS(CTAS)である。複数データベース間であれば、DB LINK経由の効率はいい。複数のプロセッサーとIOチャネルがあれば、PARALLELオプションを利用すればいい。パーティションオプションがあれば、もっと合理にコントロールできる。
  • その次、構造のまま移行する作業に限定、RMAN圧縮バックアップセットは効率である。
  • また、作業はやや繁雑だが、Transportable Tablespaceは効率である。 
  • 伝統の方法であれば、複数CSVファイルにダンプし、複数SQLLDRを起動してダイレクトパスでロードするのはパラレル効果があるが、CSVファイル上のエラーチェックなどはなくて、万の一エラーがあったら、致命的な問題になる。あまりお勧めできない。
  • 持続的な移行であれば、STREAMは移行元に負荷が低い。
  • exp/impとexpdp/impdpはあまり効率てきとはいえないが、使いやすくて、効率を要求しない場合、お勧め。
  • expdp/impdpはDB LINK経由でファイル経由せずに移行可能なので、便利である 。

exp/impで移行

exp/impとexpdp/impdpは効率があまりいいとはいえないが、使いやすくて、効率を要求しない場合、お勧め。
exp/impとexpdp/impdpを比較するなら、効率の面からみると、あまり差がない。
expdp/impdpは新機能と提携しやすくて、サーバ上で実行される。
exp/impはSQL*Net経由で、端末にデータを落とすことが可能。

expでデータのダンプ

exp userid=system/manager fromuser=schema table=(table1,table2...) file=(file1.dmp, file2.dmp,...) rows=y log=exp.log

impでデータダンプのロード

imp userid=system/manager fromuser=schema table=(table1,table2...) file=(file1.dmp, file2.dmp,...) rows=y log=imp.log

expdp/impdp で移行

exp/impとexpdp/impdpは効率があまりいいとはいえないが、使いやすくて、効率を要求しない場合、お勧め。
exp/impとexpdp/impdpを比較するなら、効率の面からみると、あまり差がない。
expdp/impdpは新機能と提携しやすくて、サーバ上で実行される。
exp/impはSQL*Net経由で、端末にデータを落とすことが可能。

expdpでデータのダンプ

create directory expdpdir as '/tmp'; 
expdp system/manager tables=employee directory=expdpdir dumpfile=expdp.dmp

impdpでデータダンプのロード

create directory imp dpdir as '/tmp'; 
impdp system/manager tables=employee directory=impdpdir dumpfile=expdp.dmp

RMANで移行

RMANのバックアップ効率は圧倒的にいい。また、データベース全体の構造と一貫性を管理できる。更に、DBAはほぼRMANのバックアップを既に日々取得しているのであれば、データ取得のステップは不要である。

RMANで移行の場合、移行元でRMANでバックアップの取得、移行先でリカバリの手順になるが、問題は移行先に同様な物理構造維持できない場合、(DISKの違い、FILE既に存在などケース)、別のパスに変更する必要がある。この場合、NEW_NAMEであるはCOVERTで、新しいパスを指定する必要がある。

RMANでバックアップの取得

rman target / nocatalog
backup database as compressed backupset plus archivelog;
exit;

RMANでバックアップのリカバリ

  • 移行先へcontrol fileとinit.oraあるいはspfileのコピー
  • init.oraあるいはspfileでcovertの設定
rman target / nocatalog
set new_name
set untile to_date('2011/11/11 11:11:11', 'yyyy/mm/dd hh24:mi:ss');
backup database as compressed backupset plus archivelog;
exit;

CREATE TABLE AS SELECT(DB LINK)で移行

CREATE TABLE AS SELECT は最も効率なデータ転送方法である。
CREATEのため、データ自体のREDO、UNDOが作成しない。
パラレルとDBLINKも利用可能である。

CREATE TABLE tablename PARALLEL AS SELECT /*+ PARALLEL(tablename)+/ ... FROM tablename;

INSERT SELECT (DB LINK)で移行

INSERT SELECT は最も効率なデータ転送方法である。
CREATEのため、データ自体のREDO、UNDOが作成しない。
パラレルとDBLINKも利用可能である。

APPENDは既存の空き領域探すコストを省いて、NOLOGGINGは最小限にREDOを出力することで
スピードを更にはやくすることができる。

INSERT /*+ PARALLEL(a) APPEND NOLOGGING*/ INTO tablename a SELECT /*+ PARALLEL(tablename)+/ ... FROM tablename;

SQLPLUS COPY コマンド

copyコマンドの文法:
usage: COPY FROM <db> TO <db> <opt> <table> { (<cols>) } USING <sel>
<db> : database string
<opt> : ONE of the keywords: APPEND, CREATE, INSERT or REPLACE
<table>: name of the destination table
<cols> : a comma-separated list of destination column aliases
<sel> : any valid SQL SELECT statement

sqlplus /nolog
SQL> set arraysize 5000
SQL> copy from serol/luo@mescp to serol/luo@ractest create test_copy_table using select * from dba_objects;
Array fetch/bind size is 5000. (arraysize is 5000)
Will commit when done. (copycommit is 0)
Maximum long size is 5000. (long is 5000)
SQLRCN in cpytbl failed: -2120
Table TEST_COPY_TABLE created.
12579 rows selected from serol@mescp.
12579 rows inserted into TEST_COPY_TABLE.
12579 rows committed into TEST_COPY_TABLE at serol@ractest.

CSV+SQLLDR

伝統の方法であれば、複数CSVファイルにダンプし、複数SQLLDRを起動してダイレクトパスでロードするのはパラレル効果があるが、CSVファイル上のエラーチェックなどはなくて、万の一エラーがあったら、致命的な問題になる。あまりお勧めできない。
CSVの形式はカンマ区切りだから簡単と言えるが、情報にカンマがある場合、処理方法は問題になる。
解決方法はコーテーションマーク""で値を指定する。すると、情報にコーテーションマーク""があれば処理方法は問題になる。
更に、UNIX、Windows、UNICODE、UTF8と多様な文字コードがある。
また、情報自体に形式説明できなくて、チェックサムがないため、問題があっても自動的な確認はできない。

DDLの取得

dbms_metadata.get_ddl('TABLE','tablename');

SQLPLUSでCSVの出力

sqlplus username/password
 
set lines 1000
set pages 0
set colsep ,
set trimspool on
 
spool data.csv
select * from tablename;
spool off
 
exit;

SQLLDRでロードする

Transportable 表領域で移行

STREAMで移行