

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Oracle ROWID 機能を AWS の PostgreSQL に移行
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws"></a>

*Amazon Web Services、Rakesh Raghav、Ramesh Pathuri*

## 概要
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws-summary"></a>

このパターンでは、Oracle データベースの `ROWID` 疑似列機能を、Amazon Aurora PostgreSQL のAmazon Relational Database Service (Amazon RDS)、Amazon Aurora PostgreSQL　互換バージョン、またはAmazon Elastic Compute Cloud (Amazon EC2)に移行するオプションについて説明しています。

Oracle データベースでは、`ROWID` 疑似列がテーブル内の行の物理アドレスです。この疑似列は、プライマリキーがテーブルに存在しない場合でも行を一意に識別するために使用されます。PostgreSQL にも `ctid` と呼ばれる同様の疑似列がありますが、`ROWID` としては使用できません。「[PostgreSQLのドキュメント](https://www.postgresql.org/docs/current/ddl-system-columns.html)」 で説明されているように、更新される場合、または`ctid` がすべての `VACUUM` のプロセスの後に変更される可能性があります。

PostgreSQLで `ROWID` 疑似列機能を作成する方法が3つあります：
+ `ROWID` の代わりに、テーブルの行を識別するプライマリキー列を使用します。
+ テーブルには論理的なプライマリキー/ユニークキー (複合キーの場合もあります) を使用します。 
+ 自動生成された値を含む列を追加し、`ROWID` を模倣するプライマリキー/ユニークキーにします。

このパターンでは、3 つの実装について順を追って説明し、各オプションの利点と欠点を説明します。

## 前提条件と制限
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws-prereqs"></a>

**前提条件**
+ アクティブなAWS アカウント
+ 手続き型言語/PostgreSQL (PL/pgSQL) コーディングの専門知識
+ ソース Oracle データベース
+ Amazon RDS for PostgreSQL または Aurora PostgreSQL 互換クラスター、または PostgreSQL データベースをホストする EC2 インスタンス

**制限事項**
+ このパターンは、`ROWID` の機能の回避策を提供します。PostgreSQL は Oracle データベースの `ROWID` と同等の機能を提供していません。

**製品バージョン**
+ PostgreSQL 11.9 以降

## アーキテクチャ
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws-architecture"></a>

**ソーステクノロジースタック**
+ Oracle Database

**ターゲットテクノロジースタック**
+ Aurora PostgreSQL 互換、Amazon RDS for PostgreSQL、または PostgreSQL データベースを備えた EC2 インスタンス

![Oracle データベースを AWS で PostgreSQL に変換](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/images/pattern-img/9a2ce994-4f68-4975-aab2-796cc20a3c82/images/6e7c2ef6-f440-476a-9003-f1f166718e15.png)


**実装オプション**

PostgreSQLで `ROWID` のサポート不足を回避するには、テーブルにプライマリキーまたはユニークインデックス、論理的プライマ的キー、またはID属性があるかどうかに応じて、3つの選択肢があります。どれを選択するかは、プロジェクトのスケジュール、現在の移行フェーズ、アプリケーションとデータベースコードへの依存関係によって異なります。


| 
| 
| オプション | 説明 | 利点 | 欠点 | 
| --- |--- |--- |--- |
| **プライマリキーまたは一意のインデックス** | Oracle テーブルにプライマリキーがある場合、このキーの属性を使用して、行を一意に識別することができます。  | 独自データベースの特徴には依存していません。。プライマリキーフィールドにはインデックスが付けられるため、パフォーマンスへの影響は最小限です。 | プライマリキーフィールドに切り替えるには、`ROWID` に依存するアプリケーションコードやデータベースコードを変更する必要があります。  | 
| **論理プライマリキー/ユニーククキー** | Oracle テーブルに論理プライマリキーがある場合、このキーの属性を使用して行を一意に識別できます。論理プライマリキーは、行を一意に識別できる 1 つまたは複数の属性で構成されますが、制約によってデータベースに適用されません。 | 独自データベースの特徴には依存していません。 | プライマリキーフィールドに切り替えるには、`ROWID` に依存するアプリケーションコードやデータベースコードを変更する必要があります。論理プライマリキーの属性にインデックスが作成されない場合、パフォーマンスに重大な影響があります。ただし、パフォーマンスの問題を防ぐために唯一のインデックスを追加できます。 | 
| **アイデンティティ属性** | Oracle テーブルにプライマリキーがない場合、`GENERATED ALWAYS AS IDENTITY` として追加のフィールドを作成できます。この属性は、テーブルにデータが挿入されるたびに常に唯一の値を生成します。ですから、データ操作言語 (DML) 操作の行を一意に識別するために使用できます。 | 独自データベースの特徴には依存していません。PostgreSQL データベースは、属性を入力し、その一意性を維持します。 | アイデンティティ属性に切り替えるには、」`ROWID` に依存するアプリケーションおよびデータベースコードを変更する必要があります。追加フィールドがインデックスされない場合、パフォーマンスに重大な影響を与えます。ただし、パフォーマンスの問題を避けるためにインデックスを追加できます。 | 

## ツール
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws-tools"></a>
+ [PostgreSQLのAmazon Relational Database Service (Amazon RDS)](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html) を使用して、 AWSクラウドで PostgreSQLリレーショナルデータベース (DB) のセットアップ、運用、スケーリングができます。
+ 「[Amazon Aurora PostgreSQL 互換エディション](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraPostgreSQL.html)」は、PostgreSQL デプロイのセットアップ、運用、スケーリングに役立つ、フルマネージド型のACID準拠のリレーショナルデータベースエンジンです。
+ 「[AWS コマンドラインインターフェイス (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)」は、オープンソースのツールであり、コマンドラインシェルのコマンドを使用して AWS サービスとやり取りすることができます。このパターンでは、AWS CLI を使用して **pgAdmin** を介して SQL コマンドを実行できます。
+ 「[pgAdmin](https://www.pgadmin.org/)」は、PostgreSQLのオープンソース管理ツールです。データベースオブジェクトの作成、管理、使用を支援するグラフィカルインターフェイスを提供します。
+ [AWS Schema Conversion Tool (AWS SCT)](https://docs.aws.amazon.com/SchemaConversionTool/latest/userguide/CHAP_Welcome.html) は、ソースデータベーススキーマとカスタムコードの大部分を、ターゲットデータベースと互換性のある形式に自動的に変換することにより、異種データベース移行をサポートします。

## エピック
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws-epics"></a>

### ソーステーブルを識別する
<a name="identify-the-source-tables"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| `ROWID` 属性を使用する Oracle テーブルを識別します。 | AWS Schema Conversion Tool (AWS SCT) を使用して、`ROWID` の機能を持つ Oracle テーブルを識別します。詳細については、「[AWS SCTドキュメント](https://docs.aws.amazon.com/SchemaConversionTool/latest/userguide/CHAP_Source.Oracle.ToPostgreSQL.html#CHAP_Source.Oracle.ToPostgreSQL.ConvertRowID)」を参照してください。<br />-または-<br />Oracle では、`DBA_TAB_COLUMNS` ビューを使用して、`ROWID` 属性を持つテーブルを識別します。これらのフィールドは、10 バイトの英数字を格納するために使用される場合があります。使用方法を決定し、必要に応じて `VARCHAR` フィールドに変換します。 | DBA または開発者 | 
| これらのテーブルを参照するコードを識別します。 | AWS SCT を使用して、移行評価レポートを生成し、`ROWID` より影響された手順を識別します。詳細については、「[AWS SCTドキュメント](https://docs.aws.amazon.com/SchemaConversionTool/latest/userguide/CHAP_AssessmentReport.html)」を参照してください。<br />-または-<br />ソース Oracle データベースでは、`dba_source` のテーブルのテキストフィールドを使用して、`ROWID`の機能を使用するオブジェクトを識別します。 | DBA または開発者 | 

### プライマリキーの使用を決定
<a name="determine-primary-key-usage"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| プライマリキーがないテーブルを識別します。 | ソース Oracle データベースで、`DBA_CONSTRAINTS` を使用してプライマリキーがないテーブルを識別します。この情報により、各テーブルの戦略を決定することを支援します。例えば、次のようになります。<pre>select dt.*<br />from dba_tables dt<br />where not exists (select 1<br />                  from all_constraints ct<br />                  where ct.owner = Dt.owner<br />                    and ct.table_name = Dt.table_name<br />                    and ct.constraint_type = 'P'<br />                  )<br />and dt.owner = '{schema}'</pre> | DBA または開発者 | 

### ソリューションを識別して適用
<a name="identify-and-apply-the-solution"></a>


| タスク | 説明 | 必要なスキル | 
| --- | --- | --- | 
| プライマリキーが定義されているテーブル、または論理的なプライマリキーを持つテーブルに変更を適用します。 | 「[追加情報](#migrate-oracle-rowid-functionality-to-postgresql-on-aws-additional)」セクションに示されているアプリケーションコードおよびデータベースコードを変更して、固有のプライマリキーまたは論理プライマリキーを使用してテーブルの行を識別するようにします。 | DBA または開発者 | 
| プライマリキーが定義されていない、または論理プライマリキーがないテーブルにフィールドを追加します。 | タイプ `GENERATED ALWAYS AS IDENTITY` の属性を追加します。「[追加情報](#migrate-oracle-rowid-functionality-to-postgresql-on-aws-additional)」セクションに表示されているアプリケーションとデータベースのコードを変更します。 | DBA または開発者 | 
| 必要に応じてインデックスを追加します。 | SQL のパフォーマンスを向上させるには、追加フィールドまたは論理プライマリキーにインデックスを追加します。 | DBA または開発者 | 

## 関連リソース
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws-resources"></a>
+ 「[PostgreSQL CTID](https://www.postgresql.org/docs/current/ddl-system-columns.html)」 (PostgreSQL ドキュメント)
+ 「[生成された列](https://www.postgresql.org/docs/current/ddl-generated-columns.html)」 (PostgreSQL ドキュメント)
+ 「[ROWID 疑似カラム](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/ROWID-Pseudocolumn.html#GUID-F6E0FBD2-983C-495D-9856-5E113A17FAF1)」 (Oracle ドキュメンテーション)

## 追加情報
<a name="migrate-oracle-rowid-functionality-to-postgresql-on-aws-additional"></a>

以下のセクションでは、Oracle と PostgreSQL のコード例を示して、これらの 3 つのアプローチを説明します。

「**シナリオ 1: プライマリユニークキーを使用**」 

以下の例では、`testrowid_s1` テーブルを、`emp_id` をプライマリキーとして作成します。

*Orackel コード: *

```
create table testrowid_s1 (emp_id integer, name varchar2(10), CONSTRAINT testrowid_pk PRIMARY KEY (emp_id));
INSERT INTO testrowid_s1(emp_id,name) values (1,'empname1');
INSERT INTO testrowid_s1(emp_id,name) values (2,'empname2');
INSERT INTO testrowid_s1(emp_id,name) values (3,'empname3');
INSERT INTO testrowid_s1(emp_id,name) values (4,'empname4');
commit;

SELECT rowid,emp_id,name FROM testrowid_s1;
ROWID                  EMP_ID NAME
------------------ ---------- ----------
AAAF3pAAAAAAAMOAAA          1 empname1
AAAF3pAAAAAAAMOAAB          2 empname2
AAAF3pAAAAAAAMOAAC          3 empname3
AAAF3pAAAAAAAMOAAD          4 empname4

UPDATE testrowid_s1 SET name = 'Ramesh' WHERE rowid = 'AAAF3pAAAAAAAMOAAB' ;
commit;

SELECT rowid,emp_id,name FROM testrowid_s1;
ROWID                  EMP_ID NAME
------------------ ---------- ----------
AAAF3pAAAAAAAMOAAA          1 empname1
AAAF3pAAAAAAAMOAAB          2 Ramesh
AAAF3pAAAAAAAMOAAC          3 empname3
AAAF3pAAAAAAAMOAAD          4 empname4
```

*PostgreSQL コード:*

```
CREATE TABLE public.testrowid_s1
(
    emp_id integer,
    name character varying,
    primary key (emp_id)
);

insert into public.testrowid_s1 (emp_id,name) values 
(1,'empname1'),(2,'empname2'),(3,'empname3'),(4,'empname4');

select emp_id,name from testrowid_s1;
 emp_id |   name   
--------+----------
      1 | empname1
      2 | empname2
      3 | empname3
      4 | empname4

update testrowid_s1 set name = 'Ramesh' where emp_id = 2 ;

select emp_id,name from testrowid_s1;
 emp_id |   name   
--------+----------
      1 | empname1
      3 | empname3
      4 | empname4
      2 | Ramesh
```

**シナリオ 2: 論理プライマリキーを使用**

以下の例では、 `testrowid_s2` テーブルを `emp_id` を配して、論理プライマリキーとして作成します。

*Orackel コード: *

```
create table testrowid_s2 (emp_id integer, name varchar2(10) );
INSERT INTO testrowid_s2(emp_id,name) values (1,'empname1');
INSERT INTO testrowid_s2(emp_id,name) values (2,'empname2');
INSERT INTO testrowid_s2(emp_id,name) values (3,'empname3');
INSERT INTO testrowid_s2(emp_id,name) values (4,'empname4');
commit;

SELECT rowid,emp_id,name FROM testrowid_s2;
ROWID                  EMP_ID NAME
------------------ ---------- ----------
AAAF3rAAAAAAAMeAAA          1 empname1
AAAF3rAAAAAAAMeAAB          2 empname2
AAAF3rAAAAAAAMeAAC          3 empname3
AAAF3rAAAAAAAMeAAD          4 empname4

UPDATE testrowid_s2 SET name = 'Ramesh' WHERE rowid = 'AAAF3rAAAAAAAMeAAB' ;
commit;

SELECT rowid,emp_id,name FROM testrowid_s2;
ROWID                  EMP_ID NAME
------------------ ---------- ----------
AAAF3rAAAAAAAMeAAA          1 empname1
AAAF3rAAAAAAAMeAAB          2 Ramesh
AAAF3rAAAAAAAMeAAC          3 empname3
AAAF3rAAAAAAAMeAAD          4 empname4
```

*PostgreSQL コード:*

```
CREATE TABLE public.testrowid_s2
(
    emp_id integer,
    name character varying
);

insert into public.testrowid_s2 (emp_id,name) values 
(1,'empname1'),(2,'empname2'),(3,'empname3'),(4,'empname4');

select emp_id,name from testrowid_s2;
 emp_id |   name   
--------+----------
      1 | empname1
      2 | empname2
      3 | empname3
      4 | empname4

update testrowid_s2 set name = 'Ramesh' where emp_id = 2 ;

select emp_id,name from testrowid_s2;
 emp_id |   name   
--------+----------
      1 | empname1
      3 | empname3
      4 | empname4
      2 | Ramesh
```

**シナリオ 3: アイデンティティ属性を使用**

以下の例では、プライマリキーなしで、またアイデンティティ属性を使用して、テーブル `testrowid_s3` を作成します。

*Oracle コード:*

```
create table testrowid_s3 (name varchar2(10));
INSERT INTO testrowid_s3(name) values ('empname1');
INSERT INTO testrowid_s3(name) values ('empname2');
INSERT INTO testrowid_s3(name) values ('empname3');
INSERT INTO testrowid_s3(name) values ('empname4');
commit;

SELECT rowid,name FROM testrowid_s3;
ROWID              NAME
------------------ ----------
AAAF3sAAAAAAAMmAAA empname1
AAAF3sAAAAAAAMmAAB empname2
AAAF3sAAAAAAAMmAAC empname3
AAAF3sAAAAAAAMmAAD empname4

UPDATE testrowid_s3 SET name = 'Ramesh' WHERE rowid = 'AAAF3sAAAAAAAMmAAB' ;
commit;

SELECT rowid,name FROM testrowid_s3;
ROWID              NAME
------------------ ----------
AAAF3sAAAAAAAMmAAA empname1
AAAF3sAAAAAAAMmAAB Ramesh
AAAF3sAAAAAAAMmAAC empname3
AAAF3sAAAAAAAMmAAD empname4
```

*PostgreSQL コード:*

```
CREATE TABLE public.testrowid_s3
(
    rowid_seq bigint generated always as identity,
    name character varying
);

insert into public.testrowid_s3 (name) values 
('empname1'),('empname2'),('empname3'),('empname4');

select rowid_seq,name from testrowid_s3;
 rowid_seq |   name   
-----------+----------
         1 | empname1
         2 | empname2
         3 | empname3
         4 | empname4

update testrowid_s3 set name = 'Ramesh' where rowid_seq = 2 ;

select rowid_seq,name from testrowid_s3;
 rowid_seq |   name   
-----------+----------
         1 | empname1
         3 | empname3
         4 | empname4
         2 | Ramesh
```