1種類のデータベース知識だけでデータベースまたはアプリケーションをOracleからPostgreSQLに移行する場合でも、2つのデータベースシステムの違いについて知っておくべきことはほとんどありません。
PostgreSQLは、世界で最も先進的なオープンソースデータベースです。 PostgreSQLコミュニティは非常に強力であり、既存のPostgreSQL機能を継続的に改善し、新しい機能も追加しています。 db-engines.comによると、PostgreSQLは2017年のDBMSです。
OracleとPostgreSQLにはいくつかの非互換性があります。一部の関数の動作は、OracleとPostgreSQLで異なります。
OracleからPostgreSQLに移行する理由
- コスト:ご存知かもしれませんが、Oracleライセンスのコストは非常に高く、パーティション分割や高可用性などの一部の機能には追加のコストがかかります。したがって、全体的には非常に高価です。
- 柔軟なオープンソースライセンスとAWSなどのパブリッククラウドプロバイダーからの簡単な可用性。
- パフォーマンスを向上させるためのオープンソースアドオンのメリット。
予備チェック
ご存知かもしれませんが、OracleからPostgreSQLへの移行は、コストと時間のかかる作業です。どの部分を移行するかを理解することが重要です。不要になったオブジェクトの移行に時間を無駄にしないでください。また、必要な履歴データがあるかどうかを確認してください。過去のメンテナンスからのバックアップデータや一時テーブルなど、不要なデータを複製する時間を無駄にしないでください。
移行評価
事前チェックの後、移行の最初のステップは、アプリケーションとデータベースオブジェクトを分析し、両方のデータベース間の非互換性を見つけて、移行に必要な時間とコストを見積もることです。
Ora2pgツールは、移行の評価に非常に役立ちます。 Oracleデータベースに接続し、自動的にスキャンしてデータを抽出し、データベース移行レポートを生成します。サンプルレポートはOra2pgで確認できます。
知っておくべきこと
OracleとPostgreSQLの違いを理解し、任意のツールを使用して変換します。 100%OracleデータベースをPostgreSQLに変換できるツールはありません。手動で変更する必要があります。移行する前に知っておくべき重要な違いのいくつかを以下で確認してください。
データ型マッピング
PostgreSQLには豊富なデータ型のセットがあります。 OracleとPostgreSQL間の重要なデータ型変換のいくつかは次のとおりです。
Oracle | PostgreSQL | コメント |
---|---|---|
VARCHAR2(n) | VARCHAR(n) | Oracleでは「n」はバイト数ですが、PostgreSQLでは「n」は文字数です |
CHAR(n) | CHAR(n) | Oracleでは「n」はバイト数ですが、PostgreSQLでは「n」は文字数です |
NUMBER(n、m) | NUMERIC(n、m) | NUMBER型はNUMERICに変換できますが、SMALLINT、INT、およびBIGINTを使用すると、パフォーマンスが向上します。 |
NUMBER(4) | SMALLINT | |
NUMBER(9) | INT | |
NUMBER(18) | BIGINT | |
NUMBER(n) | NUMERIC(n) | NUMERIC(n)、n>=19の場合 |
日付 | TIMESTAMP(0) | 両方のデータベースにはDATE型がありますが、Oracle DATE型は日付と時刻を返しますが、PostgreSQLDATE型は日付のみを返します。 |
ローカルタイムゾーンのタイムスタンプ | TIMESTAMPTZ | PostgreSQLのタイプTimestamptz(タイムゾーン付きのタイムスタンプ)は、タイムゾーン付きのOracleタイムスタンプとは異なります。これは、ローカルタイムゾーンを使用したOracleのタイムスタンプと同等ですが、このわずかな違いにより、パフォーマンスの問題やアプリケーションのバグが発生する可能性があります。 |
CLOB | テキスト | PostgreSQLTEXTタイプは最大1GBのテキストを保存できます。 |
BLOB RAW(n) | BYTEA(1 GBの制限) 大きなオブジェクト | Oracleでは、BLOBデータ型は非構造化バイナリデータをデータベースに格納します。 BLOBタイプは、最大128テラバイトのバイナリデータを格納できます。 PostgreSQL BYTEAはバイナリデータを保存しますが、最大1GBまでです。データが1GBを超える場合は、ラージオブジェクトを使用します。 |
トランザクション
Oracleデータベースは常にトランザクションを使用しますが、PostgreSQLではそれをアクティブ化する必要があります。 Oracleでは、トランザクションはステートメントの実行時に開始され、COMMITステートメントの実行時に終了します。 PostgreSQLでは、トランザクションはBEGINの実行時に開始され、COMMITステートメントの実行時に終了します。分離レベルでも問題ありません。 PostgreSQLデータベースは、Oracleデータベースが認識しているすべての分離レベルを認識しています。 PostgreSQLのデフォルトの分離レベルは読み取りコミットです。
例:
オラクル:
DELETE FROM table_name WHERE id = 120;
COMMIT;
PostgreSQL:
BEGIN;
DELETE FROM table_name WHERE id = 120;
COMMIT;
デュアルテーブル
Oracleでは、FROM句はすべてのSELECTステートメントに必須であるため、Oracleデータベースはテーブル名が不要なSELECTステートメントにDUALテーブルを使用します。 PostgreSQLでは、FROM句は必須ではないため、DUALテーブルは必要ありません。デュアルテーブルは、移植の問題を排除するためのビューとしてPostgreSQLで作成できます。 Orafceツールはこれを実装しているため、Orafceも使用できます。
例:
postgres=# SELECT CURRENT_TIMESTAMP FROM DUAL;
ERROR: relation "dual" does not exist
LINE 1: SELECT CURRENT_TIMESTAMP FROM DUAL;
^
postgres=# SELECT CURRENT_TIMESTAMP;
current_timestamp
-------------------------------
2018-03-16 09:36:01.205925+00
(1 row)
Orafceモジュールをインストールした後:
postgres=# SELECT CURRENT_TIMESTAMP FROM DUAL;
current_timestamp
-------------------------------
2018-03-16 09:36:01.205925+00
(1 row)
SYSDATE
OracleのSYSDATE関数は、日付と時刻を返します。 SYSDATE関数の動作は、場所によって異なります。 PostgreSQLにはSYSDATE関数に対応する関数はありません。 PostgreSQLには、日付と時刻を取得するための複数の方法があり、アプリケーションの目的に基づいています。
時間取得方法 | 使用する関数 |
---|---|
SQL開始時刻 | Statement_timestamp() |
トランザクション開始時間 | now()または
Transaction_timestamp() |
関数が実装された時間 | Clock_timestamp() |
次の例では、clock_timestamp()は実際の関数が実行された時刻を返し、他のstatement_timestamp()はSQLステートメントが実行を開始した時刻を返します。
postgres=# SELECT now(), statement_timestamp(), current_timestamp, transaction_timestamp(), clock_timestamp();
now | statement_timestamp | current_timestamp | transaction_timestamp | clock_timestamp
-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------
2018-03-16 09:27:56.163154+00 | 2018-03-16 09:27:56.163154+00 | 2018-03-16 09:27:56.163154+00 | 2018-03-16 09:27:56.163154+00 | 2018-03-16 09:27:56.163281+00
(1 row)
TO_DATE(2つの引数)
OracleのTO_DATE関数はDATEタイプの値(年、月、日、時、分、秒)を返し、PostgreSQLのTO_DATE(two_argument)はDATEタイプの値(年、月、日)を返します。
この非互換性の解決策は、TO_DATE()をTO_TIMESTAMP()に変換することです。 Orafceツールを使用する場合は、Orafceがこの関数を実装しているため、何も変更する必要がないため、Oracleでも同じ結果が得られます。
オラクル:
SELECT TO_DATE ('20180314121212','yyyymmddhh24miss') FROM dual;
PostgreSQL:
SELECT TO_TIMESTAMP ('20180314121212','yyyymmddhh24miss')::TIMESTAMP(0);
類義語
CREATESYNONYMはPostgreSQLではサポートされていません。 OracleではCREATESYNONYMを使用してリモートオブジェクトにアクセスしますが、PostgreSQLではSETsearch_pathを使用してリモート定義を含めることができます。
オラクル:
CREATE SYNONYM abc.table_name FOR pqr.table_name;
PostgreSQL:
SET search_path TO 'abc.table_name';
空の文字列とNULLの動作
Oracleでは、空の文字列と文字列コンテキストのNULL値は同じです。 NULLと文字列を連結すると、結果として文字列が取得されます。 PostgreSQLでは、この場合、連結結果はnullになります。 OracleではISNULL演算子を使用して文字列が空かどうかをチェックしますが、PostgreSQLでは結果は空の文字列の場合はFALSE、NULLの場合はTRUEです。
シーケンス
OracleとPostgreSQLのシーケンスの構文にはわずかな違いがあります。
オラクル:
Sequence_name.nextval
PostgreSQL:
Nextval(‘sequence_name’)
この構文を変更するには、スクリプトを作成するか、手動で変更します。
SUBSTR
OracleとPostgreSQLのSUBSTR関数の動作は異なります。 SUBSTR関数はPostgreSQLでエラーなしで機能しますが、異なる結果を返します。この違いにより、アプリケーションのバグが発生する可能性があります。
オラクル:
SELECT SUBSTR(‘ABC’,-1) FROM DUAL;
Returns ‘C’
PostgreSQL:
postgres=# SELECT SUBSTR('ABC',-1);
substr
--------
ABC
(1 row)
これに対する解決策は、PostgreSQLでOracleと同じ結果を返すOrafceSUBSTR関数を使用することです。
DELETEステートメント
Oracleでは、DELETEステートメントはFROM句なしで機能しますが、PostgreSQLではサポートされていません。 PostgreSQLのDELETEステートメントにFROM句を手動で追加する必要があります。
オラクル:
DELETE table_name WHERE column_name = 'Col_value';
PostgreSQL:
DELETE FROM table_name WHERE column_name = 'Col_value';
外部結合+
Oracleは左結合と右結合に+演算子を使用しますが、PostgreSQLはそれを使用しません。
オラクル:
SELECT a1.name1, a2.name2
FROM a1, a2
WHERE a1.code = a2.code (+);
PostgreSQL:
SELECT a1.name1, a2.name2
FROM a1
LEFT OUTER JOIN a2 ON a1.code = a2.code;
START WITH..CONNECT BY
Oracleは、階層クエリにSTARTWITH..CONNECTBYを使用します。 PostgreSQLはSTARTWITH..CONNECTBYステートメントをサポートしていません。 PostgreSQLには階層クエリ用のWITHRECURSIVEがあるため、CONNECTBYステートメントをWITHRECURSIVEステートメントに変換します。
オラクル:
SELECT
restaurant_name,
city_name
FROM
restaurants rs
START WITH rs.city_name = 'TOKYO'
CONNECT BY PRIOR rs.restaurant_name = rs.city_name;
PostgreSQL:
WITH RECURSIVE tmp AS (SELECT restaurant_name, city_name
FROM restaurants
WHERE city_name = 'TOKYO'
UNION
SELECT m.restaurant_name, m.city_name
FROM restaurants m
JOIN tmp ON tmp.restaurant_name = m.city_name)
SELECT restaurant_name, city_name FROM tmp;
PLSQLからPLPGSQLへの変換
PostgreSQLのPL/pgSQL言語は、多くの点でOracleのPL/SQL言語に似ています。これはブロック構造の命令型言語であり、すべての変数を宣言する必要があります。どちらのデータベースの割り当てでも、ループ、条件は似ています。
OracleのPL/SQLからPostgreSQLのPL/pgSQLに移植する際に留意すべき主な違い
今日のホワイトペーパーをダウンロードするClusterControlを使用したPostgreSQLの管理と自動化PostgreSQLの導入、監視、管理、スケーリングを行うために知っておくべきことについて学ぶホワイトペーパーをダウンロードする移行ツール
OracleからPostgreSQLへの移行に非常に役立つツールがいくつかあります。拡張機能として独自のツールを作成し、PostgreSQL内で使用することもできます。
オラフス
Oracle互換の関数、データ型、パッケージは、PostgreSQLと同じように使用できます。これはBSDライセンスのオープンソースツールなので、誰でもこのツールを使用できます。
主な機能のほとんどはOrafceでカバーされています。
アプリケーションは通常、これらの関数を複数回使用します。このツールを使用すると、SQLの変更コストを削減できます。
すべての機能とパッケージが正しく実装されており、十分にテストされています。
一部の機能:
- Dbms_output
- dbms_random
- utl_file –ファイルシステム関連の関数
- Dbms_pipeおよびdbms_alert
- PLVdate、PLVstr、PLVchr
- Oracle互換のDATEデータ型と、ADD_MONTHS、LAST_DAY、NEXT_DAYなどの関数。
- NVL関数
- SUBSTRおよびSUBSTRB関数
- VARCHAR2およびNVARCHAR2のサポート
- TO_DATE()
Ora2pg
Ora2Pgは、OracleデータベースをPostgreSQL互換スキーマに移行するために使用される無料のツールです。
Oracleデータベースに接続し、自動的にスキャンして、その構造またはデータを抽出し、PostgreSQLデータベースにロードできるSQLスクリプトを生成します。
OracleからPostgreSQLへの移行におけるコスト見積もりは簡単ではありません。
Ora2Pgは、すべてのデータベースオブジェクト、すべての関数、およびストアドプロシージャを検査して、Ora2Pgで自動的に変換できないオブジェクトとPL/SQLコードがまだあるかどうかを検出します。
このツールは、次の変換に非常に役立ちます。
- スキーマ変換
- PLSQLからPLPGSQLへの変換
テスト
一部の機能は両方のデータベースで同じであるため、アプリケーション全体と移行されたデータベースをテストすることは非常に重要ですが、動作は異なります。
- いくつかの一般的なシナリオを確認する必要があります:
- すべてのオブジェクトが正しく変換されているかどうかを確認します。
- すべてのDMLSが正しく機能しているかどうかを確認します。
- 両方のデータベースにいくつかのサンプルデータをロードし、結果を確認します。両方のデータベースからのSQLの結果は同じである必要があります。
- DMLのパフォーマンスを確認し、必要に応じて改善します。