データ型とそのサイズの問題
データ型とそのサイズの問題
PostgreSQLとOracleではそれぞれANSIの規格に則ったデータ型以外に独自のデータ型を持っています。こういった独自のデータ型を 移行先(この場合はOracle)でどの型で定義し、移行時にどのように変換するかを決定しなければなりません。これは単純にデータ格納だけの話ではな く、場合によっては利用するアプリケーション側にも修正が必要であることを意味します。
数値型や日付型は対応する部分が多く、移行の際にそれほど考慮すべき点はありませんが、文字データは特に注意を払う必要があります。
PostgreSQLの場合、文字型として使用される「TEXT型」は文字列長を設定せずに定義できるため、可変長文字列の格納には便利でよく使用 されます。ただし、移行の際には文字列長が定まらない「TEXT型」に入ったデータがどの位の長さであるかが大きな問題となるのです。
例えば、Oracleの可変長文字列で一般的に多く使用されるVARCHAR2型では、データのサイズが4,000バイトまでに制限されており、こ れを超えるTEXT型のデータをそのまま格納することができません。データの分割やデータの切り捨てが難しい場合(注1)は、OracleのCLOB型へ 格納することが必然となってきます。
このCLOB型は4Gバイト(注2)まで格納することが可能ですが、その扱いはすべてVARCHAR2型と同じではありません。SQL文での操作に 制限があるので、格納方式やその利用方法についてアプリケーションなどで吸収する必要を検討せねばなりません。幸いアクセラナビのアプリケーションではこ のポイントを簡単に吸収することができたため、大きな問題とはなりませんでした。
またOracle側で格納する(領域サイズを見積もる)際にLOB型は注意すべき点があります。LOB型では列長がおよそ3,900バイト未満の場 合はレコード内に、それ以上の場合には列中にポインタ情報のみを登録して別のエクステント内に格納されるという仕様があるためです。さらにLOB Indexが作成されることにより、予想以上のデータ領域を占める可能性を含んでいます。
いずれにせよ、移行前後の表の列における型定義は両方のデータベースの仕様を理解した上で、アプリケーション側の対応を細かくチェックすることが必須であるといえるでしょう。
| 移行元 | 移行先 | |||
|---|---|---|---|---|
| PostgreSQL のデータ型 |
Oracleの データ型 |
最大長 | 備考 | |
| 文字型 | char(n) | char(n) | 4,000バイト | 固定長、スペースによるパディング |
| varchar(n) | varchar2(n) | 4,000バイト | 可変長 | |
| text | varchar2(n) | 4,000バイト | ||
| text | clob | 4Gバイト(注2) | 4,000バイト以上の場合 | |
| bytea | blob | 4Gバイト(注2) | ||
| 数値型 | numeric | number | 38桁 | |
| numeric(p,s) | number(p,s) | 38桁 | pは桁数、sは小数部の桁数 | |
| 日付型 | date | date | 日付と時間を格納 | |
| バイナリ | ラージオブジェクト | bfile | 4Gバイト | 最大サイズはバージョン、プラットフォームで異なる |
移行手段の検討
第1回で述べたように、アクセラナビのデータベースを移行する際、当初は「テキスト出力して、OracleでSQL*Loaderのダイレクトモー ドを使用する」という一般的な移行方法を考えていました。それが、いくつかの問題点を考慮した結果、現実的ではないとの判断に至りました。原因はごく単純 で、以下の3点です。
- データ量
- データの中身
- 工数
データ量の多さは最初から念頭にあり、出力したデータは未加工で投入できることが前提でした。実際のデータを確認したところ、表5にあげたようなテ キスト出力には向かないデータがあり、テキスト出力した場合にデータの加工が必要であることが確認されたのです(データの中身の問題)。
- データ中に改行コードを含んでいる
- 区切り文字が選定不能
データ量が1億件以上ある表で、単純なスクリプト以外の方法で個別の列値を加工することは、かなりの工数を必要とすることが想像されました。それぞ れの理由が1点のみであれば対処可能でも、この条件が3つ揃っては現実的な選択とはいえません。よって、「テキスト出力 → OracleでSQL*Loader(注3)のダイレクトモードを使用」は不可能と判断しました。
代案としては、アクセラテクノロジが検証の際に実際に行った「Perlスクリプト+DBI+DBD」の組み合わせによる方法です。すでに実績があり、スクリプトを作成する必要もないため有力な候補ではありました。
ただし、この時点では並行稼働を想定していなかったこともあり、その移行速度の遅さが大きなネックとなります。事実、処理は「1件ずつの検索 → 登録」とする必要があり、「PostgreSQL側のインデックス検索の処理が速くないこと」と「Disk I/Oがネックであること」が、後に行ったテストで判明しました。
今回の事例では「確実性の高い移行方法」という点に着目し、その速度向上を条件に「Perlスクリプト+DBI+DBD」を採用するに至りました。
異なるDBMS間でのデータ移行では、やはりテキスト出力と付属のユーティリティによる手法が一般的ですが、このようにデータによってPerlやjavaなどのデータベース接続が可能な言語を利用することも必要な場面があります。