

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

# Amazon QLDB でのデータと履歴の使用
<a name="working-with-data"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

以下のトピックでは、*作成、読み取り、更新、削除* (CRUD) ステートメントの基本的な例を紹介します。これらのステートメントは、[QLDB コンソール](console_QLDB.md)のPartiQL エディタ、または [QLDB シェル](data-shell.md)を使用して手動で実行することができます。また、このガイドでは、台帳に変更を加えたときに、QLDB によってどのようにデータが処理されるか、そのプロセスについても一通り説明します。

QLDB は [PartiQL](https://partiql.org/) クエリ言語をサポートしています。

QLDB ドライバーを使用して同様のステートメントをプログラムで実行する方法を示すコード例については、「[ドライバーの開始方法](getting-started-driver.md)」のチュートリアルを参照してください。

**ヒント**  
以下は、QLDB で PartiQL を使用するためのヒントとベストプラクティスの簡単な要約です。  
**同時実行性とトランザクション制限を理解する** - `SELECT` クエリを含むすべてのステートメントは[オプティミスティック同時実行制御 (OCC、Optimistic Concurrency Control)](concurrency.md) 競合および[トランザクション制限](limits.md#limits.fixed) (30 秒のトランザクションタイムアウトなど) の対象になります。
**インデックスの使用** - 高基数インデックスを使用し、ターゲットとなるクエリを実行して、ステートメントを最適化し、すべてのテーブルスキャンを回避します。詳細については、「[クエリパフォーマンスの最適化](working.optimize.md)」を参照してください。
**等価述語の使用** - インデックス付きルックアップには*等価*演算子 (`=` または `IN`) が必要です。不等価演算子 (`<`、`>`、`LIKE`、`BETWEEN`) はインデックス付きルックアップの対象にならず、すべてのテーブルスキャンが実行されます。
**内部結合のみを使用する** - QLDB は現在、内部結合のみをサポートしています。ベストプラクティスとして、結合するテーブルごとにインデックス付けされたフィールドで結合します。結合基準と等価述語の両方に高基数インデックスを選択します。

**Topics**
+ [インデックスを持つテーブルの作成とドキュメントの挿入](working.create.md)
+ [データのクエリの実行](working.userdata.md)
+ [ドキュメントのメタデータのクエリの実行](working.metadata.md)
+ [BY 句を使用したドキュメント ID のクエリの実行](working.metadata.by-clause.md)
+ [ドキュメントの更新と削除](working.revisions.md)
+ [リビジョン履歴のクエリの実行](working.history.md)
+ [ドキュメントのリビジョンを秘匿化する](working.redaction.md)
+ [クエリパフォーマンスの最適化](working.optimize.md)
+ [PartiQL ステートメントの統計の取得](working.statement-stats.md)
+ [システムカタログのクエリの実行](working.catalog.md)
+ [テーブルの管理](working.manage-tables.md)
+ [インデックスの管理](working.manage-indexes.md)
+ [Amazon QLDB で割り当てられる一意の ID](working.unique-id.md)

# インデックスを持つテーブルの作成とドキュメントの挿入
<a name="working.create"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

Amazon QLDB 台帳を作成したら、最初に基本的な [CREATE TABLE](ql-reference.create-table.md) ステートメントを使用してテーブルを作成します。テーブルは [QLDB ドキュメント](ql-reference.docs.md) で構成されます。これらは、[Amazon Ion](ion.md) `struct` 形式のデータセットです。

**Topics**
+ [テーブルとインデックスの作成](#working.create.tables-indexes)
+ [ドキュメントの挿入](#working.create.insert)

## テーブルとインデックスの作成
<a name="working.create.tables-indexes"></a>

テーブルには名前空間のない単純な大文字と小文字が区別される名前を付けます。QLDB ではオープンコンテンツがサポートされており、スキーマは適用されないため、テーブル作成時に属性やデータ型を定義しません。

```
CREATE TABLE VehicleRegistration
```

```
CREATE TABLE Vehicle
```

`CREATE TABLE` ステートメントは、新しいテーブルのシステムによって割り当てられた ID を返します。QLDB では、[システムによって割り当てられた ID](working.unique-id.md) はすべて汎用一意 ID (UUID、Universally Unique Identifier) であり、それぞれ Base62 エンコード文字列で表されます。

**注記**  
オプションで、テーブルの作成中にテーブルリソースのタグを定義できます。この方法の詳細は、「[作成時のテーブルのタグ付け](working.manage-tables.md#working.manage-tables.tags)」を参照してください。

また、テーブルにインデックスを作成して、クエリのパフォーマンスを最適化することもできます。

```
CREATE INDEX ON VehicleRegistration (VIN)
```

```
CREATE INDEX ON VehicleRegistration (LicensePlateNumber)
```

```
CREATE INDEX ON Vehicle (VIN)
```

**重要**  
ドキュメントを効率的に検索するには、インデックスが必要です。インデックスがないと、QLDB はドキュメントを読み取るときにテーブルスキャンを実行する必要があります。これにより、同時実行の競合やトランザクションのタイムアウトなど、大きなテーブルでパフォーマンスの問題が発生する可能性があります。  
テーブルスキャンを回避するには、インデックス付きフィールドまたはドキュメント ID で**等価演算子 (`=` または `IN`) を使用する `WHERE` 述語句でステートメントを実行する必要があります。詳細については、「[クエリパフォーマンスの最適化](working.optimize.md)」を参照してください。

インデックスを作成する際には、以下の制約があることに注意してください。
+ インデックスは 1 つのトップレベルフィールドでのみ作成できます。複合、ネスト、一意、および関数ベースのインデックスはサポートされていません。
+ 任意の [Ion データ型](ql-reference.data-types.md) (`list`、`struct` など) でインデックスを作成できます。ただし、Ion のデータ型に関わらず、Ion 値全体の等価によってインデックス付けされたルックアップのみを実行できます。例えば、`list` 型をインデックスとして使用すると、リスト内の 1 つの項目でインデックス付けされたルックアップは実行できません。
+ クエリのパフォーマンスは、等価述語 (`WHERE indexedField = 123`、`WHERE indexedField IN (456, 789)` など) を使用する場合にのみ向上します。

  QLDB では、クエリの述語で不等式はサポートされていません。そのため、範囲でフィルタリングされるスキャンは実装されていません。
+ インデックス付きフィールドの名前は大文字と小文字の区別があり 128 文字以下で指定します。
+ QLDB でのインデックス作成は非同期です。空でないテーブルでのインデックスの作成を完了するのにかかる時間は、テーブルサイズによって異なります。詳細については、「[インデックスの管理](working.manage-indexes.md)」を参照してください。

## ドキュメントの挿入
<a name="working.create.insert"></a>

次に、テーブルにドキュメントを挿入できます。QLDB ドキュメントは Amazon Ion 形式で保存されます。次の PartiQL [INSERT](ql-reference.insert.md) ステートメントには、[Amazon QLDB コンソールの使用開始方法](getting-started.md) で使用する車両登録のサンプルデータの一部が含まれます。

```
INSERT INTO VehicleRegistration
<< {
    'VIN' : '1N4AL11D75C109151',
    'LicensePlateNumber' : 'LEWISR261LL',
    'State' : 'WA',
    'City' : 'Seattle',
    'PendingPenaltyTicketAmount' : 90.25,
    'ValidFromDate' : `2017-08-21T`,
    'ValidToDate' : `2020-05-11T`,
    'Owners' : {
        'PrimaryOwner' : { 'PersonId' : '294jJ3YUoH1IEEm8GSabOs' },
        'SecondaryOwners' : [ { 'PersonId' : '5Ufgdlnj06gF5CWcOIu64s' } ]
    }
},
{
    'VIN' : 'KM8SRDHF6EU074761',
    'LicensePlateNumber' : 'CA762X',
    'State' : 'WA',
    'City' : 'Kent',
    'PendingPenaltyTicketAmount' : 130.75,
    'ValidFromDate' : `2017-09-14T`,
    'ValidToDate' : `2020-06-25T`,
    'Owners' : {
        'PrimaryOwner' : { 'PersonId': 'IN7MvYtUjkp1GMZu0F6CG9' },
        'SecondaryOwners' : []
    }
} >>
```

```
INSERT INTO Vehicle
<< {
    'VIN' : '1N4AL11D75C109151',
    'Type' : 'Sedan',
    'Year' : 2011,
    'Make' : 'Audi',
    'Model' : 'A5',
    'Color' : 'Silver'
} ,
{
    'VIN' : 'KM8SRDHF6EU074761',
    'Type' : 'Sedan',
    'Year' : 2015,
    'Make' : 'Tesla',
    'Model' : 'Model S',
    'Color' : 'Blue'
} >>
```

**PartiQL 構文とセマンティクス**
+ フィールド名は一重引用符 (`'...'`) で囲みます。
+ 文字列値も一重引用符 (`'...'`) で囲みます。
+ タイムスタンプはバックティック (``...``) で囲みます。バックティックは、Ion リテラルを示すために使用できます。
+ 整数と小数はリテラル値で、指定する必要はありません。

PartiQL の構文とセマンティクスの詳細については、「[Amazon QLDB での PartiQL による Ion のクエリ](ql-reference.query.md)」を参照してください。

`INSERT` ステートメントで、バージョン番号が 0 というドキュメントの最初のリビジョンが作成されます。各ドキュメントを一意に識別するために、QLDB によって*ドキュメント ID* がメタデータの一部として割り当てられます。Insert ステートメントは、挿入された各ドキュメントの ID を返します。

**重要**  
QLDB ではスキーマを適用しないため、何度でもテーブルに同じドキュメントを挿入できます。それぞれの挿入ステートメントでは、ジャーナルに個別にドキュメントのエントリを実行し、QLDB がそれぞれのドキュメントに一意の ID を割り当てます。

テーブルに挿入したドキュメントのクエリを実行する方法については、「[データのクエリの実行](working.userdata.md)」に進みます。

# データのクエリの実行
<a name="working.userdata"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

*ユーザービュー*は、自分のユーザーデータの中で最新の削除されていないリビジョンのみを返します。これが Amazon QLDB のデフォルトビューです。つまり、自分のデータのみにクエリを実行するときには、特別な限定詞は必要ありません。

次のクエリ例の構文とパラメータの詳細については、「*Amazon QLDB PartiQL リファレンス*」の「[SELECT](ql-reference.select.md)」を参照してください。

**Topics**
+ [基本的なクエリ](#working.userdata.basic)
+ [射影とフィルタ](#working.userdata.projections-filters)
+ [Joins](#working.userdata.joins)
+ [ネストされたデータ](#working.userdata.nested)

## 基本的なクエリ
<a name="working.userdata.basic"></a>

基本的な `SELECT` クエリでは、テーブルに挿入したドキュメントが返されます。

**警告**  
インデックス付きルックアップなしで QLDB でクエリを実行すると、完全なテーブルスキャンが呼び出されます。PartiQL は SQL 互換であるため、このようなクエリをサポートしています。ただし、QLDB の本番環境のユースケースではテーブルスキャンを実行しないでください。テーブルスキャンより、同時実行の競合やトランザクションのタイムアウトなど、大きなテーブルでパフォーマンスの問題が発生する可能性があります。  
テーブルスキャンを回避するには、インデックス付きフィールドまたはドキュメント ID で**等価演算子を使用する `WHERE` 述語句でステートメントを実行する必要があります (例: `WHERE indexedField = 123` または `WHERE indexedField IN (456, 789)`)。詳細については、「[クエリパフォーマンスの最適化](working.optimize.md)」を参照してください。

以下のクエリは、以前に [インデックスを持つテーブルの作成とドキュメントの挿入](working.create.md) に挿入した車両登録ドキュメントの結果を示しています。結果の順序は一定ではなく、`SELECT` クエリごとに異なる場合があります。QLDB のクエリの結果の順序は変わる可能性があることに注意してください。

```
SELECT * FROM VehicleRegistration
WHERE LicensePlateNumber IN ('LEWISR261LL', 'CA762X')
```

```
{
    VIN: "1N4AL11D75C109151",
    LicensePlateNumber: "LEWISR261LL",
    State: "WA",
    City: "Seattle",
    PendingPenaltyTicketAmount: 90.25,
    ValidFromDate: 2017-08-21T,
    ValidToDate: 2020-05-11T,
    Owners: {
        PrimaryOwner: { PersonId: "294jJ3YUoH1IEEm8GSabOs" },
        SecondaryOwners: [{ PersonId: "5Ufgdlnj06gF5CWcOIu64s" }]
    }
},
{
    VIN: "KM8SRDHF6EU074761",
    LicensePlateNumber: "CA762X",
    State: "WA",
    City: "Kent",
    PendingPenaltyTicketAmount: 130.75,
    ValidFromDate: 2017-09-14T,
    ValidToDate: 2020-06-25T,
    Owners: {
        PrimaryOwner: { PersonId: "IN7MvYtUjkp1GMZu0F6CG9" },
        SecondaryOwners: []
    }
}
```

```
SELECT * FROM Vehicle
WHERE VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

```
{
    VIN: "1N4AL11D75C109151",
    Type: "Sedan",
    Year: 2011,
    Make: "Audi",
    Model: "A5",
    Color: "Silver"
},
{
    VIN: "KM8SRDHF6EU074761",
    Type: "Sedan",
    Year: 2015,
    Make: "Tesla",
    Model: "Model S",
    Color: "Blue"
}
```

**重要**  
PartiQL では、一重引用符を使用して、データ操作言語 (DML) またはクエリステートメントで文字列であることを示します。ただし、QLDB コンソールおよび QLDB シェルはクエリ結果を Amazon Ion テキスト形式で返すため、二重引用符で囲まれた文字列が表示されます。  
この構文により、PartiQL クエリ言語で SQL 互換性を維持し、Amazon Ion テキスト形式で JSON 互換性を維持できます。

## 射影とフィルタ
<a name="working.userdata.projections-filters"></a>

射影 (ターゲットの `SELECT`) およびその他の標準フィルタ (`WHERE` 句) を使用できます。次のクエリは、`VehicleRegistration` テーブルからドキュメントフィールドのサブセットを返します。以下の基準で車両をフィルタリングします。
+ **文字列フィルタ**: シアトルで登録されています。
+ **10 進数フィルタ**: 金額が `100.0` 未満の支払い保留中の反則切符がある。
+ **日付フィルタ**: 登録日は 2019 年 9 月 4 日以降有効である。

```
SELECT r.VIN, r.PendingPenaltyTicketAmount, r.Owners
FROM VehicleRegistration AS r
WHERE r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
AND r.City = 'Seattle' --string
AND r.PendingPenaltyTicketAmount < 100.0 --decimal
AND r.ValidToDate >= `2019-09-04T` --timestamp with day precision
```

```
{
    VIN: "1N4AL11D75C109151",
    PendingPenaltyTicketAmount: 90.25,
    Owners: {
        PrimaryOwner: { PersonId: "294jJ3YUoH1IEEm8GSabOs" },
        SecondaryOwners: [{ PersonId: "5Ufgdlnj06gF5CWcOIu64s" }]
    }
}
```

## Joins
<a name="working.userdata.joins"></a>

内部結合クエリを記述することもできます。以下の例では、登録車両の属性と共にすべての登録ドキュメントを返す暗黙的な内部結合クエリを示しています。

```
SELECT * FROM VehicleRegistration AS r, Vehicle AS v
WHERE r.VIN = v.VIN
AND r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

```
{
    VIN: "1N4AL11D75C109151",
    LicensePlateNumber: "LEWISR261LL",
    State: "WA",
    City: "Seattle",
    PendingPenaltyTicketAmount: 90.25,
    ValidFromDate: 2017-08-21T,
    ValidToDate: 2020-05-11T,
    Owners: {
        PrimaryOwner: { PersonId: "294jJ3YUoH1IEEm8GSabOs" },
        SecondaryOwners: [{ PersonId: "5Ufgdlnj06gF5CWcOIu64s" }]
    },
    Type: "Sedan",
    Year: 2011,
    Make: "Audi",
    Model: "A5",
    Color: "Silver"
},
{
    VIN: "KM8SRDHF6EU074761",
    LicensePlateNumber: "CA762X",
    State: "WA",
    City: "Kent",
    PendingPenaltyTicketAmount: 130.75,
    ValidFromDate: 2017-09-14T,
    ValidToDate: 2020-06-25T,
    Owners: {
        PrimaryOwner: { PersonId: "IN7MvYtUjkp1GMZu0F6CG9" },
        SecondaryOwners: []
    },
    Type: "Sedan",
    Year: 2015,
    Make: "Tesla",
    Model: "Model S",
    Color: "Blue"
}
```

また、以下のように、明示的な構文で同じ内部結合クエリを記述することもできます。

```
SELECT * FROM VehicleRegistration AS r INNER JOIN Vehicle AS v
ON r.VIN = v.VIN
WHERE r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

## ネストされたデータ
<a name="working.userdata.nested"></a>

QLDB で PartiQL を使用すると、ドキュメント内のネストしたデータをクエリできます。以下の例では、ネストされたデータを平坦化する相関サブクエリを示しています。ここで `@` 文字は構文的に省略可能です。ただしこの文字は、`Owners` という名前の別のコレクション (存在する場合) ではなく、`VehicleRegistration` 内の `Owners` 構造を必要とすることを明示的に示しています。

```
SELECT 
    r.VIN, 
    o.SecondaryOwners
FROM
    VehicleRegistration AS r, @r.Owners AS o
WHERE
    r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

```
{
    VIN: "1N4AL11D75C109151",
    SecondaryOwners: [{ PersonId: "5Ufgdlnj06gF5CWcOIu64s" }]
},
{
    VIN: "KM8SRDHF6EU074761",
    SecondaryOwners: []
}
```

以下に示しているのは、ネストされたデータを射影する `SELECT` リスト内のサブクエリと、内部結合を示しています。

```
SELECT 
    v.Make, 
    v.Model, 
    (SELECT VALUE o.PrimaryOwner.PersonId FROM @r.Owners AS o) AS PrimaryOwner
FROM 
    VehicleRegistration AS r, Vehicle AS v
WHERE 
    r.VIN = v.VIN AND r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

```
{
    Make: "Audi",
    Model: "A5",
    PrimaryOwner: ["294jJ3YUoH1IEEm8GSabOs"]
},
{
    Make: "Tesla",
    Model: "Model S",
    PrimaryOwner: ["IN7MvYtUjkp1GMZu0F6CG9"]
}
```

以下では、`VehicleRegistration` ドキュメントについて、`Owners.SecondaryOwners` リスト内の各個人の `PersonId` とインデックス番号 (序数) を返します。

```
SELECT s.PersonId, owner_idx
FROM VehicleRegistration AS r, @r.Owners.SecondaryOwners AS s AT owner_idx
WHERE r.VIN = '1N4AL11D75C109151'
```

```
{
    PersonId: "5Ufgdlnj06gF5CWcOIu64s",
    owner_idx: 0
}
```

ドキュメントのメタデータのクエリを実行する方法については、「[ドキュメントのメタデータのクエリの実行](working.metadata.md)」に進みます。

# ドキュメントのメタデータのクエリの実行
<a name="working.metadata"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

`INSERT` ステートメントで、バージョン番号が 0 というドキュメントの最初のリビジョンが作成されます。各ドキュメントを一意に識別するために、Amazon QLDB によって*ドキュメント ID* がメタデータの一部として割り当てられます。

QLDB は、ドキュメント ID とバージョン番号に加えて、各ドキュメントの他のシステム生成メタデータをテーブルに保存します。このメタデータには、トランザクション情報、ジャーナル属性、およびドキュメントのハッシュ値が含まれます。

システムによって割り当てられた ID はすべて汎用一意 ID (UUID、Universally Unique Identifier) であり、それぞれ Base62 エンコード文字列で表されます。詳細については、「[Amazon QLDB で割り当てられる一意の ID](working.unique-id.md)」を参照してください。

**Topics**
+ [コミット済みビュー](#working.metadata.committed)
+ [コミットされたビューとユーザービューへの参加](#working.metadata.committed-joins)

## コミット済みビュー
<a name="working.metadata.committed"></a>

コミット済みビューのクエリを実行して、ドキュメントのメタデータにアクセスできます。このビューでは、システムで定義したテーブルからドキュメントを返します。このテーブルはユーザーテーブルに直接対応するものです。これには、自分のデータもシステムによって生成されたメタデータも、最後にコミットされ削除されていないリビジョンで含まれます。このビューのクエリを実行するには、クエリ内のテーブル名にプレフィックス `_ql_committed_` を追加します。(プレフィックス `_ql_` は、システムオブジェクトの QLDB に割り当てられます。)

```
SELECT * FROM _ql_committed_VehicleRegistration AS r
WHERE r.data.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

このクエリの出力では、以前に [インデックスを持つテーブルの作成とドキュメントの挿入](working.create.md) に挿入したデータを使用して、それぞれの削除されていないドキュメントの最新リビジョンのシステムコンテンツを表示します。システムドキュメントには、`metadata` フィールドのネストされたメタデータ、`data` フィールドのネストされたユーザーデータがあります。

```
{
    blockAddress:{
        strandId:"JdxjkR9bSYB5jMHWcI464T",
        sequenceNo:14
    },
    hash:{{wCsmM6qD4STxz0WYmE+47nZvWtcCz9D6zNtCiM5GoWg=}},
    data:{
        VIN: "1N4AL11D75C109151",
        LicensePlateNumber: "LEWISR261LL",
        State: "WA",
        City: "Seattle",
        PendingPenaltyTicketAmount: 90.25,
        ValidFromDate: 2017-08-21T,
        ValidToDate: 2020-05-11T,
        Owners: {
            PrimaryOwner: { PersonId: "294jJ3YUoH1IEEm8GSabOs" },
            SecondaryOwners: [{ PersonId: "5Ufgdlnj06gF5CWcOIu64s" }]
        }
    },
    metadata:{
        id:"3Qv67yjXEwB9SjmvkuG6Cp",
        version:0,
        txTime:2019-06-05T20:53:321d-3Z,
        txId:"HgXAkLjAtV0HQ4lNYdzX60"
    }
},
{
    blockAddress:{
        strandId:"JdxjkR9bSYB5jMHWcI464T",
        sequenceNo:14
    },
    hash:{{wPuwH60TtcCvg/23BFp+redRXuCALkbDihkEvCX22Jk=}},
    data:{
        VIN: "KM8SRDHF6EU074761",
        LicensePlateNumber: "CA762X",
        State: "WA",
        City: "Kent",
        PendingPenaltyTicketAmount: 130.75,
        ValidFromDate: 2017-09-14T,
        ValidToDate: 2020-06-25T,
        Owners: {
            PrimaryOwner: { PersonId: "IN7MvYtUjkp1GMZu0F6CG9" },
            SecondaryOwners: []
        }
    },
    metadata:{
        id:"JOzfB3lWqGU727mpPeWyxg",
        version:0,
        txTime:2019-06-05T20:53:321d-3Z,
        txId:"HgXAkLjAtV0HQ4lNYdzX60"
    }
}
```

**コミット済みビューフィールド**
+ `blockAddress`: ドキュメントリビジョンがコミットされた台帳のジャーナルのブロックの場所。暗号検証に使用するアドレスには、以下の 2 つのフィールドがあります。
  + `strandId` - ブロックを含むジャーナルストランドの一意の ID。
  + `sequenceNo`: ストランド内でブロックの場所を指定するインデックス番号。
**注記**  
この例にあるドキュメントにはどちらにも、`sequenceNo` が同じ `blockAddress` が含まれています。これらのドキュメントは、1 回のトランザクションで (この場合には、1 つのステートメントに) 挿入されたため、同じブロックにコミットされています。
+ `hash`: ドキュメントリビジョンを一意に表す SHA-256 Ion ハッシュ値。ハッシュは `data` フィールドと `metadata` フィールドを対象とし、[暗号検証](verification.md)に使用できます。
+ `data` – ドキュメントのユーザーデータ属性。

  リビジョンを秘匿化すると、この `data` 構造は `dataHash` フィールドに置き換えられ、その値は削除された `data` 構造の Ion ハッシュになります。
+ `metadata`: ドキュメントのメタデータ属性。
  + `id`: ドキュメントのシステムによって割り当てられた一意の ID。
  + `version` – ドキュメントのバージョン番号。これは、ドキュメントリビジョンごとに増えていく、0 から始まる整数です。
  + `txTime`: ジャーナルにドキュメントリビジョンがコミットされたときのタイムスタンプ。
  + `txId`: ドキュメントリビジョンをコミットしたトランザクションの一意の ID。

## コミットされたビューとユーザービューへの参加
<a name="working.metadata.committed-joins"></a>

コミットされたビュー内のテーブルをユーザービューのテーブルと結合するクエリを記述できます。例えば、あるテーブルのドキュメント `id` を別のテーブルのユーザー定義フィールドと結合することができます。

次のクエリは、`PersonId` の `DriversLicense` と `Person` という名前の 2 つのテーブルをドキュメント `id` のフィールドとそれぞれ結合します。後者にはコミット済みビューを使用します。

```
SELECT * FROM DriversLicense AS d INNER JOIN _ql_committed_Person AS p
ON d.PersonId = p.metadata.id
WHERE p.metadata.id = '1CWScY2qHYI9G88C2SjvtH'
```

デフォルトのユーザービューでドキュメント ID フィールドのクエリを実行する方法については、「[BY 句を使用したドキュメント ID のクエリの実行](working.metadata.by-clause.md)」に進みます。

# BY 句を使用したドキュメント ID のクエリの実行
<a name="working.metadata.by-clause"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

一意の識別子 (車両の VIN など) 用にフィールドを定義することはできますが、実際のドキュメントの一意の識別子は、「[ドキュメントの挿入](working.create.md#working.create.insert)」で説明されているとおり、`id` メタデータのフィールドになります。このため、`id` フィールドを使用して、各テーブル間の関係を作成できます。

ドキュメントの `id` フィールドは、コミット済みビューでのみ直接アクセスできますが、`BY` 句を使用すれば、デフォルトのユーザービューに射影することもできます。例として、以下のクエリとその結果を参照してください。

```
SELECT r_id, r.VIN, r.LicensePlateNumber, r.State, r.City, r.Owners
FROM VehicleRegistration AS r BY r_id
WHERE r_id = '3Qv67yjXEwB9SjmvkuG6Cp'
```

```
{
    r_id: "3Qv67yjXEwB9SjmvkuG6Cp",
    VIN: "1N4AL11D75C109151",
    LicensePlateNumber: "LEWISR261LL",
    State: "WA",
    City: "Seattle",
    Owners: {
        PrimaryOwner: { PersonId: "294jJ3YUoH1IEEm8GSabOs" },
        SecondaryOwners: [{ PersonId: "5Ufgdlnj06gF5CWcOIu64s" }]
    }
}
```

このクエリで、`r_id` は、`BY` キーワードを使用して `FROM` 句で宣言されているユーザー定義のエイリアスです。この `r_id` エイリアスは、クエリの結果セットで各ドキュメントの `id` メタデータフィールドにバインドされます。`SELECT` 句と*ユーザービュー*のクエリの `WHERE` 句にこのエイリアスを使用できます。

ただし、他のメタデータの属性にアクセスするには、コミット済みビューでクエリを実行する必要があります。

## ドキュメント ID での結合
<a name="working.by-clause.joining-on-id"></a>

あるテーブルのドキュメント `id` を別のテーブルのユーザー定義フィールド内の外部キーとして使用しているとします。`BY` 句を使用すると、これらのフィールドに 2 つのテーブルの内部結合クエリを記述できます (前のトピックの「[コミットされたビューとユーザービューへの参加](working.metadata.md#working.metadata.committed-joins)」と同様)。

次の例は、`DriversLicense` の `Person` と `PersonId` という名前の 2 つのテーブルをドキュメント `id` のフィールドとそれぞれ結合します。後者には `BY` 句を使用します。

```
SELECT * FROM DriversLicense AS d INNER JOIN Person AS p BY pid
ON d.PersonId = pid
WHERE pid = '1CWScY2qHYI9G88C2SjvtH'
```

テーブル内のドキュメントを変更する方法については、「[ドキュメントの更新と削除](working.revisions.md)」に進みます。

# ドキュメントの更新と削除
<a name="working.revisions"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

Amazon QLDB の*ドキュメントリビジョン*は、一意のドキュメント ID によって識別される一連のドキュメントの 1 つのバージョンを表す Amazon Ion 構造です。すべてのリビジョンには、ユーザーデータとシステム生成メタデータの両方を含む、ドキュメントの完全なデータセットが含まれます。各リビジョンは、ドキュメント ID と 0 から始まるバージョン番号を組み合わせてそれぞれ識別されます。

ドキュメントを更新すると、QLDB によって、同じドキュメント ID と増加したバージョン番号を持つ新しいリビジョンが作成されます。ドキュメントのライフサイクルは、テーブルから削除されたときに終了します。つまり、同じドキュメント ID のドキュメントリビジョンを再度作成することはできません。

## ドキュメントのリビジョン
<a name="working.revisions.making"></a>

たとえば、次のステートメントに新しい車両登録を挿入し、登録都市をアップデートしてから、登録を削除します。その結果、3 つのドキュメントリビジョンが出来上がります。

```
INSERT INTO VehicleRegistration
{
    'VIN' : '1HVBBAANXWH544237',
    'LicensePlateNumber' : 'LS477D',
    'State' : 'WA',
    'City' : 'Tacoma',
    'PendingPenaltyTicketAmount' : 42.20,
    'ValidFromDate' : `2011-10-26T`,
    'ValidToDate' : `2023-09-25T`,
    'Owners' : {
        'PrimaryOwner' : { 'PersonId': 'KmA3XPKKFqYCP2zhR3d0Ho' },
        'SecondaryOwners' : []
    }
}
```

**注記**  
Insert ステートメントと他の DML ステートメントは、影響を受ける各ドキュメントの ID を返します。次のトピックの履歴機能に必要なため、続行する前に、この ID を保存してください。次のクエリを使用してドキュメント ID を検索することもできます。  

```
SELECT r_id FROM VehicleRegistration AS r BY r_id
WHERE r.VIN = '1HVBBAANXWH544237'
```

```
UPDATE VehicleRegistration AS r 
SET r.City = 'Bellevue' 
WHERE r.VIN = '1HVBBAANXWH544237'
```

```
DELETE FROM VehicleRegistration AS r 
WHERE r.VIN = '1HVBBAANXWH544237'
```

これらの DML ステートメントの構文の例と詳細については、「*Amazon QLDB PartiQL リファレンス*」の「[UPDATE](ql-reference.update.md)」と「[DELETE](ql-reference.delete.md)」を参照してください。

ドキュメント内の特定の要素を挿入および削除するには、`FROM` キーワードで始まる `UPDATE` ステートメントまたはその他の DML ステートメントを使用できます。詳細と例については、「[FROM (INSERT、REMOVE、または SET)](ql-reference.from.md)リファレンス」を参照してください。

ドキュメントを削除した後は、コミット済みビューまたはユーザービューでそのドキュメントのクエリを実行できなくなります。組み込みの履歴関数を使用してこのドキュメントのリビジョン履歴のクエリを実行する方法については、「[リビジョン履歴のクエリの実行](working.history.md)」に進みます。

# リビジョン履歴のクエリの実行
<a name="working.history"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

Amazon QLDB は、テーブル内にあるすべてのドキュメントの履歴全体を保存します。組み込みの履歴関数のクエリを実行することで、「[ドキュメントの更新と削除](working.revisions.md)」で前に挿入、更新、削除された車両登録ドキュメントの 3 つのリビジョンすべてを表示できます。

**Topics**
+ [履歴関数](#working.history.function)
+ [履歴クエリの例](#working.history.example)

## 履歴関数
<a name="working.history.function"></a>

QLDB の履歴関数は、テーブルのシステム定義ビューからリビジョンを返す PartiQL の拡張機能です。そのため、お客様のデータも、コミット済みビューと同じスキーマにあるその関連メタデータも両方含まれます。

**[Syntax]** (構文)

```
SELECT * FROM history( table_name | 'table_id' [, `start-time` [, `end-time` ] ] ) AS h
[ WHERE h.metadata.id = 'id' ]
```引数

***table\$1name* \$1 '*table\$1id*'**  
テーブル名またはテーブル ID のいずれか。テーブル名は PartiQL 識別子であり、二重引用符で囲んでも、引用符で囲まなくてもかまいません。テーブル ID は文字列リテラルであり、単一引用符で囲む必要があります。テーブル ID の使用の詳細については、「[非アクティブなテーブルの履歴に対するクエリの実行](working.manage-tables.md#working.history.inactive-table)」を参照してください。

**`*start-time*`、`*end-time*`**  
(オプション) リビジョンがアクティブだった時間範囲を指定します。*これらのパラメータでは、リビジョンがトランザクションのジャーナルにコミットされた時間範囲を指定しません。*  
開始時刻と終了時刻は、バックティック (``...``) で示すことができる Ion タイムスタンプリテラルです。詳細については、「[Amazon QLDB での PartiQL による Ion のクエリ](ql-reference.query.md)」を参照してください。  
これらの時間パラメータには、次の動作があります。  
+ *開始時刻*と*終了時刻*は、両方とも含まれます。両方とも、[ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) の日時形式、協定世界時 (UTC) にしてください。
+ *開始時刻*は、過去の任意の日付で *終了時刻*以前の時刻に設定してください。
+ *終了時刻*は、協定世界時 (UTC) における現在の日時よりも前の時刻にしてください。
+ *開始時刻*を指定し、*終了時刻*を指定しない場合、クエリではデフォルトで*終了時刻*が現在の日付と時刻に設定されます。どちらも指定しない場合、クエリでは履歴全体が返されます。

**'*id*'**  
(オプション) リビジョン履歴のクエリを実行するドキュメント ID。一重引用符を使用して表記されます。

**ヒント**  
ベストプラクティスとして、履歴クエリは日付範囲 (*start-time* および *end-time*) とドキュメント ID (`metadata.id`) の両方で修飾します。QLDB では、すべての `SELECT` クエリはトランザクションで処理され、[トランザクションタイムアウト制限](limits.md#limits.fixed)の対象になります。  
履歴クエリでは、テーブルで作成するインデックスは使用されません。QLDB 履歴はドキュメント ID によってのみインデックス付けされるため、現時点では追加の履歴インデックスを作成することはできません。開始時刻と終了時刻を含む履歴クエリでは、日付範囲修飾のメリットが得られます。

## 履歴クエリの例
<a name="working.history.example"></a>

車両登録ドキュメントの履歴のクエリを実行するために、「[ドキュメントの更新と削除](working.revisions.md)」で保存しておいた `id` を使用します。例えば、次の履歴クエリは、`2019-06-05T00:00:00Z` と `2019-06-05T23:59:59Z` の間アクティブだったドキュメント ID `ADR2Ll1fGsU4Jr4EqTdnQF` のリビジョンを返します。

**注記**  
開始時刻と終了時刻のパラメータでは、リビジョンがトランザクション内のジャーナルにコミットされた時間範囲を指定*しない*ことに注意してください。例えば、リビジョンが `2019-06-05T00:00:00Z` 以前にコミットされ、その開始時刻を過ぎてもアクティブなままだった場合、この例のクエリは結果にそのリビジョンを返します。

必ず、`id`、開始時刻、終了時刻を適した独自の値に置き換えてください。

```
SELECT * FROM history(VehicleRegistration, `2019-06-05T00:00:00Z`, `2019-06-05T23:59:59Z`) AS h
WHERE h.metadata.id = 'ADR2Ll1fGsU4Jr4EqTdnQF' --replace with your id
```

クエリ結果は以下のようになります。

```
{
    blockAddress:{
        strandId:"JdxjkR9bSYB5jMHWcI464T",
        sequenceNo:14
    },
    hash:{{B2wYwrHKOWsmIBmxUgPRrTx9lv36tMlod2xVvWNiTbo=}},
    data: {
        VIN: "1HVBBAANXWH544237",
        LicensePlateNumber: "LS477D",
        State: "WA",
        City: "Tacoma",
        PendingPenaltyTicketAmount: 42.20,
        ValidFromDate: 2011-10-26T,
        ValidToDate: 2023-09-25T,
        Owners: {
            PrimaryOwner: { PersonId: "KmA3XPKKFqYCP2zhR3d0Ho" },
            SecondaryOwners: []
        }
    },
    metadata:{
        id:"ADR2Ll1fGsU4Jr4EqTdnQF",
        version:0,
        txTime:2019-06-05T20:53:321d-3Z,
        txId:"HgXAkLjAtV0HQ4lNYdzX60"
    }
},
{
    blockAddress:{
        strandId:"JdxjkR9bSYB5jMHWcI464T",
        sequenceNo:17
    },
    hash:{{LGSFZ4iEYWZeMwmAqcxxNyT4wbCtuMOmFCj8pEd6Mp0=}},
    data: {
        VIN: "1HVBBAANXWH544237",
        LicensePlateNumber: "LS477D",
        State: "WA",
        PendingPenaltyTicketAmount: 42.20,
        ValidFromDate: 2011-10-26T,
        ValidToDate: 2023-09-25T,
        Owners: {
            PrimaryOwner: { PersonId: "KmA3XPKKFqYCP2zhR3d0Ho" },
            SecondaryOwners: []
        },
        City: "Bellevue"
    },
    metadata:{
        id:"ADR2Ll1fGsU4Jr4EqTdnQF",
        version:1,
        txTime:2019-06-05T21:01:442d-3Z,
        txId:"9cArhIQV5xf5Tf5vtsPwPq"
    }
},
{
    blockAddress:{
        strandId:"JdxjkR9bSYB5jMHWcI464T",
        sequenceNo:19
    },
    hash:{{7bm5DUwpqJFGrmZpb7h9wAxtvggYLPcXq+LAobi9fDg=}},
    metadata:{
        id:"ADR2Ll1fGsU4Jr4EqTdnQF",
        version:2,
        txTime:2019-06-05T21:03:76d-3Z,
        txId:"9GslbtDtpVHAgYghR5FXbZ"
    }
}
```

出力には、メタデータの属性が含まれ、それぞれのアイテムが変更された日時、また関連するトランザクション内容の詳細を確認できます。このデータで、以下を確認できます。
+ ドキュメントはシステムによって割り当てられた `id`: `ADR2Ll1fGsU4Jr4EqTdnQF` で個々に識別されます。これは Base62 でエンコードされた文字列で表される UUID です。
+ `INSERT` ステートメントで、ドキュメントの最初のリビジョン (バージョン`0`) を作成します。
+ その後、更新のたびに新しいリビジョンが作成され、同じドキュメント `id` にバージョン番号が増えていきます。
+ `txId` フィールドは各リビジョンをコミットしたトランザクションを示し、`txTime` は各リビジョンがコミットされた日時を示します。
+ `DELETE` ステートメントでは新しいリビジョンが作成されますが、これはドキュメントの最後のリビジョンになります。この最終的なリビジョンには、メタデータのみが含まれます。

リビジョンを完全に削除する方法については、[ドキュメントのリビジョンを秘匿化する](working.redaction.md) に進んでください。

# ドキュメントのリビジョンを秘匿化する
<a name="working.redaction"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

Amazon QLDB では、`DELETE` ステートメントは、削除済みとしてマークする新しいリビジョンを作成することによってのみドキュメントを論理的に削除します。QLDB テーブルの履歴にある使用頻度の低いドキュメントリビジョンを完全に削除できるデータの秘匿化オペレーションもサポートしています。

**注記**  
2021 年 7 月 22 日より前に作成された台帳は、現時点では秘匿化の対象にはなりません。台帳の作成時間は Amazon QLDB コンソールで確認できます。

秘匿化オペレーションでは、指定されたリビジョンのユーザーデータのみが削除され、ジャーナルシーケンスとドキュメントメタデータは変更されません。これにより、台帳の全体的なデータの整合性が維持されます。

QLDB でのデータの秘匿化を開始する前に、「Amazon QLDB PartiQL リファレンス」の「[秘匿化に関する考慮事項と制約事項](ql-stored-procedures.redact_revision.md#ql-stored-procedures.redact_revision.considerations)」を必ず確認してください。

**Topics**
+ [秘匿化ストアドプロシージャ](#working.redaction.stored-proc)
+ [秘匿化が完了したかどうかの確認](#working.redaction.check-completion)
+ [秘匿化の例](#working.redaction.example)
+ [アクティブなリビジョンの削除と秘匿化](#working.redaction.active-revision)
+ [リビジョン内の特定のフィールドを秘匿化する](#working.redaction.field)

## 秘匿化ストアドプロシージャ
<a name="working.redaction.stored-proc"></a>

[REDACT\$1REVISION](ql-stored-procedures.redact_revision.md) ストアドプロシージャを使用して、台帳内の使用頻度の低い個別のリビジョンを完全に削除できます。このストアドプロシージャは、インデックス付きストレージとジャーナルストレージの両方で、指定されたリビジョンのユーザーデータをすべて削除します。ただし、ジャーナルシーケンスと、ドキュメント ID やハッシュなどのドキュメントメタデータは変更されません。この操作を元に戻すことはできません。

指定されたドキュメントリビジョンは、履歴上使用頻度の低いリビジョンでなければなりません。ドキュメントの最新の有効なリビジョンは、秘匿化の対象にはなりません。

複数のリビジョンを秘匿化するには、リビジョンごとに 1 回ストアドプロシージャを実行する必要があります。トランザクションごとに 1 つのリビジョンを秘匿化できます。

**[Syntax]** (構文)

```
EXEC REDACT_REVISION `block-address`, 'table-id', 'document-id'
```引数

`*block-address*`  
秘匿化されたドキュメントリビジョンのジャーナルブロックの場所。アドレスは、`strandId` と `sequenceNo` という 2 つのフィールドを含む Amazon Ion 構造です。  
これはバックスティックで示される Ion リテラル値です。以下に例を示します。  

```
`{strandId:"JdxjkR9bSYB5jMHWcI464T", sequenceNo:17}`
```

'*table-id*'  
一重引用符で囲まれた、秘匿化するドキュメントのリビジョンがあったテーブルの一意の ID。

'*document-id*'  
一重引用符で囲まれた、秘匿化対象のリビジョンの一意のドキュメント ID。

## 秘匿化が完了したかどうかの確認
<a name="working.redaction.check-completion"></a>

このストアドプロシージャを実行して秘匿化リクエストを送信すると、QLDB はデータの秘匿化を非同期的に処理します。完了すると、リビジョン内の (`data` 構造によって表される) ユーザーデータは完全に削除されます。秘匿化リクエストが完了したかどうかを確認するには、次のいずれかを使用します。
+ [ジャーナルエクスポート](export-journal.md)
+ [ジャーナルストリーム](streams.md)
+ [ゲットブロック API オペレーション](https://docs.aws.amazon.com/qldb/latest/developerguide/API_GetBlock.html)
+ [ゲットリビジョン API オペレーション](https://docs.aws.amazon.com/qldb/latest/developerguide/API_GetRevision.html)
+ [履歴関数](working.history.md#working.history.function) – **注:** ジャーナルで秘匿化が完了した後、履歴クエリに秘匿化の結果が表示されるまでに時間がかかることがあります。非同期の秘匿化が完了すると、一部のリビジョンが他のリビジョンよりも先に秘匿化されるかもしれませんが、履歴クエリでは最終的に完了した結果が表示されます。

リビジョンの秘匿化が完了すると、リビジョンの `data` 構造は新しい `dataHash` フィールドに置き換えられます。このフィールドの値は、次の例に示されるように、削除された `data` 構造の Ion ハッシュです。その結果、台帳は全体的なデータ整合性を維持し、既存の検証 API オペレーションを通じて暗号的に検証できる状態を維持します。検証の詳細については、「[Amazon QLDB でのデータ検証](verification.md)」を参照してください。

## 秘匿化の例
<a name="working.redaction.example"></a>

以前に「[リビジョン履歴のクエリの実行](working.history.md)」で確認した車両登録書類を考えてみましょう。2 番目のリビジョン (`version:1`) を秘匿化するとします。次のクエリ例は、秘匿化前のリビジョンを示しています。クエリ結果では、秘匿化される `data` 構造が*赤色の斜体*で強調表示されます。

```
SELECT * FROM history(VehicleRegistration) AS h
WHERE h.metadata.id = 'ADR2Ll1fGsU4Jr4EqTdnQF' --replace with your id
AND h.metadata.version = 1
```

```
{
    blockAddress:{
        strandId:"JdxjkR9bSYB5jMHWcI464T",
        sequenceNo:17
    },
    hash:{{LGSFZ4iEYWZeMwmAqcxxNyT4wbCtuMOmFCj8pEd6Mp0=}},
    data: {
        VIN: "1HVBBAANXWH544237",
        LicensePlateNumber: "LS477D",
        State: "WA",
        PendingPenaltyTicketAmount: 42.20,
        ValidFromDate: 2011-10-26T,
        ValidToDate: 2023-09-25T,
        Owners: {
            PrimaryOwner: { PersonId: "KmA3XPKKFqYCP2zhR3d0Ho" },
            SecondaryOwners: []
        },
        City: "Bellevue"
    },
    metadata:{
        id:"ADR2Ll1fGsU4Jr4EqTdnQF",
        version:1,
        txTime:2019-06-05T21:01:442d-3Z,
        txId:"9cArhIQV5xf5Tf5vtsPwPq"
    }
}
```

この値は `REDACT_REVISION` ストアドプロシージャに渡す必要があるため、クエリ結果の `blockAddress` に注意してください。次に、次のように[システムカタログ](working.catalog.md)をクエリして、`VehicleRegistration` テーブルの一意の ID を見つけます。

```
SELECT tableId FROM information_schema.user_tables
WHERE name = 'VehicleRegistration'
```

このテーブル ID をドキュメント ID とブロックアドレスとともに使用して `REDACT_REVISION` を実行します。テーブル ID とドキュメント ID は一重引用符で囲む必要がある文字列リテラルで、ブロックアドレスはバックティックスで囲まれた Ion リテラルです。必要に応じて、これらの引数を独自の値に置き換えてください。

```
EXEC REDACT_REVISION `{strandId:"JdxjkR9bSYB5jMHWcI464T", sequenceNo:17}`, '5PLf9SXwndd63lPaSIa0O6', 'ADR2Ll1fGsU4Jr4EqTdnQF'
```

**ヒント**  
QLDB コンソールまたは QLDB シェルでテーブル ID またはドキュメント ID (または任意の文字列リテラル値) をクエリすると、戻り値は二重引用符で囲まれます。ただし、`REDACT_REVISION` ストアドプロシージャのテーブル ID 引数とドキュメント ID 引数を指定する場合は、値を一重引用符で囲む必要があります。  
これは、ステートメントを PartiQL 形式で記述しても、QLDB は Amazon Ion 形式で結果を返すからです。QLDB での PartiQL の構文とセマンティクスの詳細については、「[PartiQL での Ion のクエリ](ql-reference.query.md)」を参照してください。

有効な秘匿化リクエストでは、秘匿化中のドキュメントリビジョンを表す Ion 構造体が次のように返されます。

```
{
  blockAddress: {
    strandId: "JdxjkR9bSYB5jMHWcI464T",
    sequenceNo: 17
  },
  tableId: "5PLf9SXwndd63lPaSIa0O6",
  documentId: "ADR2Ll1fGsU4Jr4EqTdnQF",
  version: 1
}
```

このストアドプロシージャを実行すると、QLDB は秘匿化リクエストを非同期的に処理します。秘匿化が完了すると、`data` 構造は完全に削除され、新しい *`dataHash`* フィールドに置き換えられます。このフィールドの値は、次のとおり、削除された `data` 構造の Ion ハッシュです。

**注記**  
この `dataHash` の例は情報提供のみを目的として、実際に計算されたハッシュ値ではありません。

```
{
    blockAddress:{
        strandId:"JdxjkR9bSYB5jMHWcI464T",
        sequenceNo:17
    },
    hash:{{LGSFZ4iEYWZeMwmAqcxxNyT4wbCtuMOmFCj8pEd6Mp0=}},
    dataHash: {{s83jd7sfhsdfhksj7hskjdfjfpIPP/DP2hvionas2d4=}},
    metadata:{
        id:"ADR2Ll1fGsU4Jr4EqTdnQF",
        version:1,
        txTime:2019-06-05T21:01:442d-3Z,
        txId:"9cArhIQV5xf5Tf5vtsPwPq"
    }
}
```

## アクティブなリビジョンの削除と秘匿化
<a name="working.redaction.active-revision"></a>

アクティブなドキュメントのリビジョン (つまり、各ドキュメントの削除されていない最新のリビジョン) は、データの秘匿化の対象にはなりません。アクティブなリビジョンを秘匿化するには、まずそのリビジョンを更新または削除する必要があります。これにより、以前にアクティブだったリビジョンが履歴に移動し、秘匿化が可能になります。

ユースケースでドキュメント全体を削除済みとしてマークする必要がある場合は、まず [DELETE](ql-reference.delete.md) ステートメントを使用します。例えば、次のステートメントは VIN が `1HVBBAANXWH544237` の `VehicleRegistration` ドキュメントを論理的に削除します。

```
DELETE FROM VehicleRegistration AS r
WHERE r.VIN = '1HVBBAANXWH544237'
```

次に、前述のように、削除前の前のリビジョンを秘匿化します。必要であれば、以前のリビジョンを個別に秘匿化することもできます。

ユースケースでドキュメントをアクティブのままにしておく必要がある場合は、まず [UPDATE](ql-reference.update.md) または [FROM](ql-reference.from.md) ステートメントを使用して、秘匿化するフィールドを隠したり削除したりします。このプロセスの説明は、以下のセクションに記載されています。

## リビジョン内の特定のフィールドを秘匿化する
<a name="working.redaction.field"></a>

QLDB は、ドキュメントリビジョン内の特定のフィールドの秘匿化をサポートしていません。そのためには、まず [UPDATE-REMOVE](ql-reference.update.md) ステートメントまたは [FROM-REMOVE](ql-reference.from.md) ステートメントを使用して、既存のフィールドをリビジョンから削除します。例えば、次のステートメントは VIN が `1HVBBAANXWH544237` の `LicensePlateNumber` フィールドを `VehicleRegistration` ドキュメントから削除します。

```
UPDATE VehicleRegistration AS r
REMOVE r.LicensePlateNumber
WHERE r.VIN = '1HVBBAANXWH544237'
```

次に、前述のように、削除の前に以前のリビジョンを秘匿化します。必要であれば、この削除済みフィールドを含む以前のリビジョンを個別に秘匿化することもできます。

クエリを最適化する方法については、「[クエリパフォーマンスの最適化](working.optimize.md)」に進みます。

# クエリパフォーマンスの最適化
<a name="working.optimize"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

Amazon QLDB は、高性能なオンライントランザクション処理 (OLTP) ワークロードのニーズに対応することを目的としています。つまり、SQL のようなクエリ機能をサポートしているにもかかわらず、QLDB は特定のクエリパターンのセットに最適化されます。これらのクエリパターンを操作するには、アプリケーションとそのデータモデルを設計することが重要です。それ以外の場合は、テーブルが大きくなるにつれて、クエリのレイテンシー、トランザクションのタイムアウト、同時実行の競合など、重大なパフォーマンスの問題が発生します。

このセクションでは、QLDB のクエリ制約を説明し、これらの制約を考慮した最適なクエリを記述するためのガイダンスを提供します。

**Topics**
+ [トランザクションタイムアウト制限](#working.optimize.txn-timeout)
+ [同時実行の競合](#working.optimize.occ)
+ [最適なクエリパターン](#working.optimize.patterns)
+ [回避すべきクエリパターン](#working.optimize.avoid)
+ [パフォーマンスのモニタリング](#working.optimize.monitor)

## トランザクションタイムアウト制限
<a name="working.optimize.txn-timeout"></a>

QLDB では、すべての PartiQL ステートメント (すべての `SELECT` クエリを含む) はトランザクションで処理され、[トランザクションタイムアウト制限](limits.md#limits.fixed)の対象になります。トランザクションは、コミットされるまでに最大 **30 秒**間実行できます。この制限を超えると、QLDB はトランザクションに対して行われたすべての作業を拒否し、トランザクションを実行する[セッション](concurrency.md#concurrency.sessions)を破棄します。この制限は、サービスのクライアントがトランザクションを開始し、トランザクションをコミットまたはキャンセルしないことで、セッションがリークするのを防ぎます。

## 同時実行の競合
<a name="working.optimize.occ"></a>

QLDB では、*オプティミスティック同時実行制御* (OCC) を使用して同時実行制御が実行されます。最適でないクエリは、OCC の競合が増える可能性もあります。OCC の詳細については、「[Amazon QLDB 同時実行モデル](concurrency.md)」を参照してください。

## 最適なクエリパターン
<a name="working.optimize.patterns"></a>

ベストプラクティスとして、インデックス付きフィールドまたはドキュメント ID でフィルタリングする `WHERE` 述語句を使用してステートメントを実行することをお勧めします。QLDB では、ドキュメントを効率的に検索するために、インデックス付きフィールドに*等価*演算子 (`=` または `IN`) が必要です。

以下に、[ユーザービュー](working.userdata.md)の最適なクエリパターンの例を示します。

```
--Indexed field (VIN) lookup using the = operator
SELECT * FROM VehicleRegistration
WHERE VIN = '1N4AL11D75C109151'

--Indexed field (VIN) AND non-indexed field (City) lookup
SELECT * FROM VehicleRegistration
WHERE VIN = '1N4AL11D75C109151' AND City = 'Seattle'

--Indexed field (VIN) lookup using the IN operator
SELECT * FROM VehicleRegistration
WHERE VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')

--Document ID (r_id) lookup using the BY clause
SELECT * FROM VehicleRegistration BY r_id
WHERE r_id = '3Qv67yjXEwB9SjmvkuG6Cp'
```

これらのパターンに従わないクエリは*テーブル全体のスキャン*を呼び出します。テーブルスキャンは、大きなテーブルのクエリや大きな結果セットを返すクエリに対してトランザクションタイムアウトを引き起こす可能性があります。さらに、[競合するトランザクションと OCC の競合につながる](concurrency.md#concurrency.indexes)可能性もあります。

**高基数インデックス**

高基数値を含むフィールドのインデックスを作成することをお勧めします。例えば、`VehicleRegistration` テーブル内の `VIN` と `LicensePlateNumber` のフィールドは、一意にすることを意図したインデックス付きフィールドです。

ステータスコード、住所の都道府県、郵便番号などの低基数フィールドのインデックス作成は避けてください。このようなフィールドのインデックスを作成すると、クエリによって、*トランザクションのタイムアウトや、意図しない OCC の競合が発生する可能性が高くなる*大きな結果セットが生成される可能性があります。

**コミット済みビュークエリ**

[コミット済みビュー](working.metadata.md)で実行するクエリは、ユーザービュークエリと同じ最適化ガイドラインに従います。テーブル上に作成するインデックスは、コミット済みビューのクエリにも使用されます。

**履歴関数クエリ**

[履歴関数クエリ](working.history.md)では、テーブルで作成するインデックスは使用されません。QLDB 履歴はドキュメント ID によってのみインデックス付けされるため、現時点では追加の履歴インデックスを作成することはできません。

ベストプラクティスとして、履歴クエリを日付範囲 (*開始時刻*および*終了時刻*) とドキュメント ID (`metadata.id`) の両方で修飾します。開始時刻と終了時刻を含む履歴クエリでは、日付範囲修飾のメリットが得られます。

**内部結合クエリ**

内部結合クエリでは、少なくとも結合の右側にあるテーブルのインデックス付きフィールドを含む結合条件を使用します。結合インデックスがない場合、結合クエリは複数のテーブルスキャンを呼び出します。結合の左側のテーブルのすべてのドキュメントに対して、クエリは右側のテーブルを完全にスキャンします。ベストプラクティスは、少なくとも 1 つのテーブルに `WHERE` 等価述語を指定することに加えて、結合している各テーブルにインデックス付けされているフィールドに結合することです。

例えば、次のクエリでは、`VehicleRegistration` と `Vehicle` のテーブルをそれぞれの `VIN` フィールドに結合します。その両方にインデックスが付けられます。このクエリには、`VehicleRegistration.VIN` の等価述語もあります。

```
SELECT * FROM VehicleRegistration AS r INNER JOIN Vehicle AS v
ON r.VIN = v.VIN
WHERE r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

結合クエリの結合基準と等価述語の両方に高基数インデックスを選択します。

## 回避すべきクエリパターン
<a name="working.optimize.avoid"></a>

次に、QLDB の大きいテーブルでは適切に拡張されない**最適ではない**ステートメントの例をいくつか示します。クエリは最終的にトランザクションタイムアウトになるため、時間の経過とともに増加するテーブルについては、これらのタイプのクエリに依存しないことを強くお勧めします。テーブルにはサイズの異なるドキュメントが含まれているため、インデックス付けされていないクエリに対して正確な制限を定義することは困難です。

```
--No predicate clause
SELECT * FROM Vehicle

--COUNT() is not an optimized function
SELECT COUNT(*) FROM Vehicle

--Low-cardinality predicate
SELECT * FROM Vehicle WHERE Color = 'Silver'

--Inequality (>) does not qualify for indexed lookup
SELECT * FROM Vehicle WHERE "Year" > 2019

--Inequality (LIKE)
SELECT * FROM Vehicle WHERE VIN LIKE '1N4AL%'

--Inequality (BETWEEN)
SELECT SUM(PendingPenaltyTicketAmount) FROM VehicleRegistration
WHERE ValidToDate BETWEEN `2020-01-01T` AND `2020-07-01T`

--No predicate clause
DELETE FROM Vehicle

--No document id, and no date range for the history() function
SELECT * FROM history(Vehicle)
```

一般的に、QLDB の本番ユースケースに、次のタイプのクエリパターンを実行することは*お勧めしません*。
+ オンライン分析処理 (OLAP) クエリ
+ 述語句のない探索的クエリ
+ レポート作成クエリ
+ テキスト検索

代わりに、分析ユースケースに、最適化された目的別データベースサービスへのデータのストリーミングをすることをお勧めします。例えば、QLDB データを Amazon OpenSearch Service にストリーム配信すると、ドキュメントに対して全文検索機能を提供することができます。このユースケースを示すサンプルアプリケーションについては、GitHub リポジトリ [aws-samples/amazon-qldb-streaming-amazon-opensearch-service-sample-python](https://github.com/aws-samples/amazon-qldb-streaming-amazon-opensearch-service-sample-python) を参照してください。QLDB ストリーミングの詳細については、「[Amazon QLDB からのジャーナルデータのストリーミング](streams.md)」を参照してください。

## パフォーマンスのモニタリング
<a name="working.optimize.monitor"></a>

QLDB ドライバーは、ステートメントの結果オブジェクトで消費された I/O 使用量とタイミング情報を提供します。これらのメトリクスを使用して、非効率な PartiQL ステートメントを特定できます。詳細については、「[PartiQL ステートメントの統計の取得](working.statement-stats.md)」を参照してください。

また、Amazon CloudWatch を使用して、データオペレーションに対する台帳のパフォーマンスを追跡することもできます。指定された `LedgerName` と `CommandType` に対する `CommandLatency` メトリクスをモニタリングします。詳細については、「[Amazon CloudWatch でのモニタリング](monitoring-cloudwatch.md)」を参照してください。QLDB がコマンドを使用してデータオペレーションを管理する方法については、「[ドライバーによるセッション管理](driver-session-management.md)」を参照してください。

# PartiQL ステートメントの統計の取得
<a name="working.statement-stats"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

Amazon QLDB は、より効率的な PartiQL ステートメントを実行して、QLDB の使用を最適化する際に役立つステートメント実行の統計を提供します。QLDB は、ステートメントの結果と共にこれらの統計を返します。これには、消費された I/O 使用量とサーバー側の処理時間を定量化するメトリクスが含まれており、非効率的なステートメントを特定するために使用できます。

この機能は現在、すべてのサポートされている言語において、[QLDB コンソール](console_QLDB.md)、[QLDB シェル](data-shell.md)、最新バージョンの [QLDB ドライバー](getting-started-driver.md)の PartiQL エディタで使用できます。コンソールでクエリ履歴のステートメント統計を表示することもできます。

**Topics**
+ [I/O 使用量](#statement-stats.io-usage)
+ [タイミング情報](#statement-stats.timing-information)

## I/O 使用量
<a name="statement-stats.io-usage"></a>

I/O 使用量のメトリクスは、読み取り I/O リクエストの数を示します。読み取り I/O リクエストの数が予想よりも多い場合は、インデックスがないなど、ステートメントが最適化されていないことを示します。前のトピック「*クエリパフォーマンスの最適化*」の「[最適なクエリパターン](working.optimize.md#working.optimize.patterns)」を確認することをお勧めします。

**注記**  
空でないテーブルで `CREATE INDEX` ステートメントを実行した場合、I/O 使用量メトリクスには、同期インデックス作成呼び出しの読み取りリクエストのみが含まれます。  
QLDB は、テーブル内の既存のドキュメントのインデックスを非同期的に構築します。これらの非同期読み取りリクエストは、ステートメント結果からの I/O 使用量メトリクスには含まれません。非同期読み取りリクエストは個別に課金され、インデックスの構築が完了した後に読み取り I/O の合計に追加されます。

### QLDB コンソールの使用
<a name="statement-stats.io-usage.con"></a>

QLDB コンソールを使用してステートメントの読み取り I/O 使用量を取得するには、次のステップを実行します。

1. Amazon QLDB コンソール ([https://console.aws.amazon.com/qldb](https://console.aws.amazon.com/qldb)) を開きます。

1. ナビゲーションペイン内で **[PartiQL エディタ]** を選択します。

1. 台帳のドロップダウンリストから台帳を選択します。

1. クエリエディタウィンドウで、選択したステートメントを入力し、**[Run]** (実行) を選択します。以下はクエリの例です。

   ```
   SELECT * FROM testTable WHERE firstName = 'Jim'
   ```

   ステートメントを実行するには、キーボードショートカット Ctrl\$1Enter (Windows の場合) または Cmd\$1Return (macOS の場合) を使用することもできます。キーボードショートカットの詳細については、「[PartiQL エディタのキーボードショートカット](console_QLDB.md#console_QLDB.partiql-editor-shortcuts)」を参照してください。

1. クエリエディタウィンドウの下に、クエリ結果にはステートメントによって行われた読み取りリクエストの数である read I/Os が含まれます。

次のステップを実行して、クエリ履歴の読み取り I/O を表示することもできます。

1. ナビゲーションペインで、**[PartiQL エディタ]** の **[最近のクエリ]** を選択します。

1. **[Read I/Os]** (読み取り I/O) 列には、各ステートメントによって行われた読み取りリクエストの数が表示されます。

### QLDB ドライバーの使用
<a name="statement-stats.io-usage.driver"></a>

QLDB ドライバーを使用してステートメントの I/O 使用量を取得するには、結果のストリームカーソルまたはバッファ済みカーソルの `getConsumedIOs` オペレーションを呼び出します。

次のコード例は、読み取り I/O をステートメント結果の*ストリームカーソル*から取得する方法を示します。

------
#### [ Java ]

```
import com.amazon.ion.IonSystem;
import com.amazon.ion.IonValue;
import com.amazon.ion.system.IonSystemBuilder;
import software.amazon.qldb.IOUsage;
import software.amazon.qldb.Result;

IonSystem ionSystem = IonSystemBuilder.standard().build();
IonValue ionFirstName = ionSystem.newString("Jim");

driver.execute(txn -> {
    Result result = txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);

    for (IonValue ionValue : result) {
        // User code here to handle results
    }

    IOUsage ioUsage = result.getConsumedIOs();
    long readIOs = ioUsage.getReadIOs();
});
```

------
#### [ .NET ]

```
using Amazon.IonDotnet.Builders;
using Amazon.IonDotnet.Tree;
using Amazon.QLDB.Driver;
using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult;

// This is one way of creating Ion values. We can also use a ValueFactory.
// For more details, see: https://docs.aws.amazon.com/qldb/latest/developerguide/driver-cookbook-dotnet.html#cookbook-dotnet.ion
IIonValue ionFirstName = IonLoader.Default.Load("Jim");

await driver.Execute(async txn =>
{
    IAsyncResult result = await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);

    // Iterate through stream cursor to accumulate read IOs.
    await foreach (IIonValue ionValue in result)
    {
        // User code here to handle results.
        // Warning: It is bad practice to rely on results within a lambda block, unless
        // it is to check the state of a result. This is because lambdas are retryable.
    }

    var ioUsage = result.GetConsumedIOs();
    var readIOs = ioUsage?.ReadIOs;
});
```

**注記**  
同期コードに変換するには、`await` と `async` のキーワードを削除して、`IAsyncResult` 型を `IResult` に変更します。

------
#### [ Go ]

```
import (
    "context"
    "fmt"
    "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)

driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    result, err := txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim")

    if err != nil {
        panic(err)
    }

    for result.Next(txn) {
        // User code here to handle results
    }

    ioUsage := result.GetConsumedIOs()
    readIOs := *ioUsage.GetReadIOs()
    fmt.Println(readIOs)
    return nil,nil
})
```

------
#### [ Node.js ]

```
import { IOUsage, ResultReadable, TransactionExecutor } from "amazon-qldb-driver-nodejs";

await driver.executeLambda(async (txn: TransactionExecutor) => {
    const result: ResultReadable = await txn.executeAndStreamResults("SELECT * FROM testTable WHERE firstName = ?", "Jim");

    for await (const chunk of result) {
        // User code here to handle results
    }

    const ioUsage: IOUsage = result.getConsumedIOs();
    const readIOs: number = ioUsage.getReadIOs();
});
```

------
#### [ Python ]

```
def get_read_ios(transaction_executor):
    cursor = transaction_executor.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim")

    for row in cursor:
        # User code here to handle results
        pass

    consumed_ios = cursor.get_consumed_ios()
    read_ios = consumed_ios.get('ReadIOs')

qldb_driver.execute_lambda(lambda txn: get_read_ios(txn))
```

------

次のコード例は、読み取り I/O をステートメント結果の*バッファ済みカーソル*から取得する方法を示します。これは、`ExecuteStatement` と `FetchPage` リクエストから読み取り I/O の合計を返します。

------
#### [ Java ]

```
import com.amazon.ion.IonSystem;
import com.amazon.ion.IonValue;
import com.amazon.ion.system.IonSystemBuilder;
import software.amazon.qldb.IOUsage;
import software.amazon.qldb.Result;

IonSystem ionSystem = IonSystemBuilder.standard().build();
IonValue ionFirstName = ionSystem.newString("Jim");

Result result = driver.execute(txn -> {
    return txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);
});

IOUsage ioUsage = result.getConsumedIOs();
long readIOs = ioUsage.getReadIOs();
```

------
#### [ .NET ]

```
using Amazon.IonDotnet.Builders;
using Amazon.IonDotnet.Tree;
using Amazon.QLDB.Driver;
using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult;

IIonValue ionFirstName = IonLoader.Default.Load("Jim");

IAsyncResult result = await driver.Execute(async txn =>
{
    return await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);
});

var ioUsage = result.GetConsumedIOs();
var readIOs = ioUsage?.ReadIOs;
```

**注記**  
同期コードに変換するには、`await` と `async` のキーワードを削除して、`IAsyncResult` 型を `IResult` に変更します。

------
#### [ Go ]

```
import (
    "context"
    "fmt"
    "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)

result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    result, err :=  txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim")
    if err != nil {
        return nil, err
    }
    return txn.BufferResult(result)
})

if err != nil {
    panic(err)
}

qldbResult := result.(*qldbdriver.BufferedResult)
ioUsage := qldbResult.GetConsumedIOs()
readIOs := *ioUsage.GetReadIOs()
fmt.Println(readIOs)
```

------
#### [ Node.js ]

```
import { IOUsage, Result, TransactionExecutor } from "amazon-qldb-driver-nodejs";

const result: Result = await driver.executeLambda(async (txn: TransactionExecutor) => {
    return await txn.execute("SELECT * FROM testTable WHERE firstName = ?", "Jim");
});

const ioUsage: IOUsage = result.getConsumedIOs();
const readIOs: number = ioUsage.getReadIOs();
```

------
#### [ Python ]

```
cursor = qldb_driver.execute_lambda(
    lambda txn: txn.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim"))

consumed_ios = cursor.get_consumed_ios()
read_ios = consumed_ios.get('ReadIOs')
```

------

**注記**  
ストリームカーソルは、結果セットをページ分割するため、ステートフルです。したがって、`getConsumedIOs` と `getTimingInformation` オペレーションは、呼び出す時間以降の蓄積されたメトリクスを返します。  
バッファ済みカーソルは、結果セットをメモリにバッファリングし、蓄積されたメトリクスの合計を返します。

## タイミング情報
<a name="statement-stats.timing-information"></a>

タイミング情報メトリクスは、サーバー側の処理時間をミリ秒単位で表します。サーバー側の処理時間は、QLDB がステートメントの処理に費やす期間として定義されます。これには、ネットワーク呼び出しや一時停止にかかる時間は含まれません。このメトリクスは、QLDB サービス側の処理時間とクライアント側の処理時間を区別します。

### QLDB コンソールの使用
<a name="statement-stats.timing-information.con"></a>

QLDB コンソールを使用してステートメントのタイミング情報を取得するには、次のステップを実行します。

1. Amazon QLDB コンソール ([https://console.aws.amazon.com/qldb](https://console.aws.amazon.com/qldb)) を開きます。

1. ナビゲーションペイン内で **[PartiQL エディタ]** を選択します。

1. 台帳のドロップダウンリストから台帳を選択します。

1. クエリエディタウィンドウで、選択したステートメントを入力し、**[Run]** (実行) を選択します。以下はクエリの例です。

   ```
   SELECT * FROM testTable WHERE firstName = 'Jim'
   ```

   ステートメントを実行するには、キーボードショートカット Ctrl\$1Enter (Windows の場合) または Cmd\$1Return (macOS の場合) を使用することもできます。キーボードショートカットの詳細については、「[PartiQL エディタのキーボードショートカット](console_QLDB.md#console_QLDB.partiql-editor-shortcuts)」を参照してください。

1. クエリエディタウィンドウの下のクエリ結果には、QLDB がステートメントリクエストを受信してからレスポンスを送信するまでの時間であるサーバー側のレイテンシーが含まれます。これはクエリ時間全体のサブセットです。

次のステップを実行して、クエリ履歴のタイミング情報を表示することもできます。

1. ナビゲーションペインで、**[PartiQL エディタ]** の **[最近のクエリ]** を選択します。

1. **[実行時間 (ms)]** 列には、各ステートメントのこのタイミング情報が表示されます。

### QLDB ドライバーの使用
<a name="statement-stats.timing-information.driver"></a>

QLDB ドライバーを使用してステートメントのタイミング情報を取得するには、結果のストリームカーソルまたはバッファ済みカーソルの `getTimingInformation` オペレーションを呼び出します。

次のコード例は、処理時間をステートメント結果の*ストリームカーソル*から取得する方法を示します。

------
#### [ Java ]

```
import com.amazon.ion.IonSystem;
import com.amazon.ion.IonValue;
import com.amazon.ion.system.IonSystemBuilder;
import software.amazon.qldb.Result;
import software.amazon.qldb.TimingInformation;

IonSystem ionSystem = IonSystemBuilder.standard().build();
IonValue ionFirstName = ionSystem.newString("Jim");

driver.execute(txn -> {
    Result result = txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);

    for (IonValue ionValue : result) {
        // User code here to handle results
    }

    TimingInformation timingInformation = result.getTimingInformation();
    long processingTimeMilliseconds = timingInformation.getProcessingTimeMilliseconds();
});
```

------
#### [ .NET ]

```
using Amazon.IonDotnet.Builders;
using Amazon.IonDotnet.Tree;
using Amazon.QLDB.Driver;
using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult;

IIonValue ionFirstName = IonLoader.Default.Load("Jim");

await driver.Execute(async txn =>
{
    IAsyncResult result = await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);

    // Iterate through stream cursor to accumulate processing time.
    await foreach(IIonValue ionValue in result)
    {
        // User code here to handle results.
        // Warning: It is bad practice to rely on results within a lambda block, unless
        // it is to check the state of a result. This is because lambdas are retryable.
    }

    var timingInformation = result.GetTimingInformation();
    var processingTimeMilliseconds = timingInformation?.ProcessingTimeMilliseconds;
});
```

**注記**  
同期コードに変換するには、`await` と `async` のキーワードを削除して、`IAsyncResult` 型を `IResult` に変更します。

------
#### [ Go ]

```
import (
    "context"
    "fmt"
    "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)

driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    result, err := txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim")

    if err != nil {
        panic(err)
    }

    for result.Next(txn) {
        // User code here to handle results
    }

    timingInformation := result.GetTimingInformation()
    processingTimeMilliseconds := *timingInformation.GetProcessingTimeMilliseconds()
    fmt.Println(processingTimeMilliseconds)
    return nil, nil
})
```

------
#### [ Node.js ]

```
import { ResultReadable, TimingInformation, TransactionExecutor } from "amazon-qldb-driver-nodejs";

await driver.executeLambda(async (txn: TransactionExecutor) => {
    const result: ResultReadable = await txn.executeAndStreamResults("SELECT * FROM testTable WHERE firstName = ?", "Jim");

    for await (const chunk of result) {
        // User code here to handle results
    }

    const timingInformation: TimingInformation = result.getTimingInformation();
    const processingTimeMilliseconds: number = timingInformation.getProcessingTimeMilliseconds();
});
```

------
#### [ Python ]

```
def get_processing_time_milliseconds(transaction_executor):
    cursor = transaction_executor.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim")

    for row in cursor:
        # User code here to handle results
        pass

    timing_information = cursor.get_timing_information()
    processing_time_milliseconds = timing_information.get('ProcessingTimeMilliseconds')

qldb_driver.execute_lambda(lambda txn: get_processing_time_milliseconds(txn))
```

------

次のコード例は、処理時間をステートメント結果の*バッファ済みカーソル*から取得する方法を示します。これは、`ExecuteStatement` と `FetchPage` リクエストから処理時間の合計を返します。

------
#### [ Java ]

```
import com.amazon.ion.IonSystem;
import com.amazon.ion.IonValue;
import com.amazon.ion.system.IonSystemBuilder;
import software.amazon.qldb.Result;
import software.amazon.qldb.TimingInformation;

IonSystem ionSystem = IonSystemBuilder.standard().build();
IonValue ionFirstName = ionSystem.newString("Jim");

Result result = driver.execute(txn -> {
    return txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);
});

TimingInformation timingInformation = result.getTimingInformation();
long processingTimeMilliseconds = timingInformation.getProcessingTimeMilliseconds();
```

------
#### [ .NET ]

```
using Amazon.IonDotnet.Builders;
using Amazon.IonDotnet.Tree;
using Amazon.QLDB.Driver;
using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult;

IIonValue ionFirstName = IonLoader.Default.Load("Jim");

IAsyncResult result = await driver.Execute(async txn =>
{
    return await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName);
});

var timingInformation = result.GetTimingInformation();
var processingTimeMilliseconds = timingInformation?.ProcessingTimeMilliseconds;
```

**注記**  
同期コードに変換するには、`await` と `async` のキーワードを削除して、`IAsyncResult` 型を `IResult` に変更します。

------
#### [ Go ]

```
import (
    "context"
    "fmt"
    "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)

result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    result, err :=  txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim")
    if err != nil {
        return nil, err
    }
    return txn.BufferResult(result)
})

if err != nil {
    panic(err)
}

qldbResult := result.(*qldbdriver.BufferedResult)
timingInformation := qldbResult.GetTimingInformation()
processingTimeMilliseconds := *timingInformation.GetProcessingTimeMilliseconds()
fmt.Println(processingTimeMilliseconds)
```

------
#### [ Node.js ]

```
import { Result, TimingInformation, TransactionExecutor } from "amazon-qldb-driver-nodejs";

const result: Result = await driver.executeLambda(async (txn: TransactionExecutor) => {
    return await txn.execute("SELECT * FROM testTable WHERE firstName = ?", "Jim");
});

const timingInformation: TimingInformation = result.getTimingInformation();
const processingTimeMilliseconds: number = timingInformation.getProcessingTimeMilliseconds();
```

------
#### [ Python ]

```
cursor = qldb_driver.execute_lambda(
    lambda txn: txn.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim"))

timing_information = cursor.get_timing_information()
processing_time_milliseconds = timing_information.get('ProcessingTimeMilliseconds')
```

------

**注記**  
ストリームカーソルは、結果セットをページ分割するため、ステートフルです。したがって、`getConsumedIOs` と `getTimingInformation` オペレーションは、呼び出す時間以降の蓄積されたメトリクスを返します。  
バッファ済みカーソルは、結果セットをメモリにバッファリングし、蓄積されたメトリクスの合計を返します。

システムカタログをクエリする方法については、[システムカタログのクエリの実行](working.catalog.md) に進みます。

# システムカタログのクエリの実行
<a name="working.catalog"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

Amazon QLDB 台帳で作成する各テーブルには、システムによって割り当てられた一意の ID があります。システムカタログテーブル `information_schema.user_tables` のクエリを実行することで、テーブルの ID、インデックスのリスト、およびその他のメタデータを見つけることができます。

システムによって割り当てられた ID はすべて汎用一意 ID (UUID、Universally Unique Identifier) であり、それぞれ Base62 エンコード文字列で表されます。詳細については、「[Amazon QLDB で割り当てられる一意の ID](working.unique-id.md)」を参照してください。

以下の例では、`VehicleRegistration` テーブルのメタデータ属性を返すクエリの結果を示しています。

```
SELECT * FROM information_schema.user_tables
WHERE name = 'VehicleRegistration'
```

```
{
    tableId: "5PLf9SXwndd63lPaSIa0O6",
    name: "VehicleRegistration",
    indexes: [
        { indexId: "Djg2nt0yIs2GY0T29Kud1z", expr: "[VIN]", status: "ONLINE" },
        { indexId: "4tPW3fUhaVhDinRgKRLhGU", expr: "[LicensePlateNumber]", status: "BUILDING" }
    ],
    status: "ACTIVE"
}
```

**テーブルメタデータフィールド**
+ `tableId`: テーブルの一意の ID。
+ `name`: テーブル名。
+ `indexes`: テーブルのインデックスのリスト。
  + `indexId`: インデックスの一意の ID。
  + `expr`: インデックス付きドキュメントパス。このフィールドは、`[fieldName]` 形式の文字列です。
  + `status`: インデックスの現在のステータス (`BUILDING`、`FINALIZING`、`ONLINE`、`FAILED`、または `DELETING`)。QLDB は、ステータスが `ONLINE` になるまで、クエリのインデックスを使用しません。
  + `message`: インデックスに `FAILED` ステータスがある理由を説明するエラーメッセージ。このフィールドは、失敗したインデックスにのみ含まれます。
+ `status`: テーブルの現在のステータス (`ACTIVE` または `INACTIVE`)。テーブルは、`DROP` すると `INACTIVE` になります。

`DROP TABLE` および `UNDROP TABLE` ステートメントを使用してテーブルを管理する方法については、[テーブルの管理](working.manage-tables.md) に進みます。

# テーブルの管理
<a name="working.manage-tables"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

このセクションでは、Amazon QLDB の `DROP TABLE` および `UNDROP TABLE` ステートメントを使用してテーブルを管理する方法について説明します。また、テーブルの作成中にテーブルにタグを付ける方法についても説明します。作成できるアクティブなテーブル数と合計テーブル数のクォータは、[Amazon QLDB でのクォータと制限](limits.md#limits.fixed) で定義します。

**Topics**
+ [作成時のテーブルのタグ付け](#working.manage-tables.tags)
+ [テーブルの削除](#working.manage-tables.drop)
+ [非アクティブなテーブルの履歴に対するクエリの実行](#working.history.inactive-table)
+ [テーブルを再アクティブ化](#working.history.undrop-table)

## 作成時のテーブルのタグ付け
<a name="working.manage-tables.tags"></a>

**注記**  
 作成時のテーブルのタグ付けは、現在 `STANDARD` 許可モードの台帳のみでサポートされています。

テーブルリソースにタグ付けすることができます。既存のテーブルのタグを管理するには、 AWS マネジメントコンソール または API オペレーション `TagResource`、`UntagResource`、および `ListTagsForResource` を使用します。詳細については、「[Amazon QLDB リソースのタグ付け](tagging.md)」を参照してください。

テーブルの作成中に、QLDB コンソールを使用するか、`CREATE TABLE` PartiQL ステートメントで指定して、テーブルタグを定義することもできます。次の例では、`Vehicle` という名前のテーブルをタグ `environment=production` を付けて作成します。

```
CREATE TABLE Vehicle WITH (aws_tags = `{'environment': 'production'}`)
```

作成時にリソースにタグ付けすることで、リソース作成後にカスタムタグ付けスクリプトを実行する必要がなくなります。テーブルにタグを付けると、それらのタグに基づいてテーブルへのアクセスを制御できます。例えば、特定のタグを持つテーブルにのみフルアクセスを付与できます。JSON ポリシーの例については、「[テーブルタグに基づくすべてのアクションへのフルアクセス](security_iam_id-based-policy-examples.md#security_iam_id-based-policy-examples-full-tags)」を参照してください。

## テーブルの削除
<a name="working.manage-tables.drop"></a>

テーブルを削除するには、基本 [DROP TABLE](ql-reference.drop-table.md) ステートメントを使用します。QLDB でのテーブルの削除は、テーブルを無効にしているだけです。

例えば、次のステートメントは、`VehicleRegistration` テーブルを非アクティブにします。

```
DROP TABLE VehicleRegistration
```

`DROP TABLE` ステートメントは、テーブルのシステムで割り当てられた ID を返します。`VehicleRegistration` のステータスは、システムカタログテーブル [information\$1schema.user\$1tables](working.catalog.md) で `INACTIVE` になっています。

```
SELECT status FROM information_schema.user_tables
WHERE name = 'VehicleRegistration'
```

## 非アクティブなテーブルの履歴に対するクエリの実行
<a name="working.history.inactive-table"></a>

最初の入力引数として、テーブル名ではなくテーブル ID を渡しても、QLDB [履歴関数](working.history.md#working.history.function) のクエリを実行できます。非アクティブなテーブルの履歴をクエリするには、テーブル ID を使用する必要があります。テーブルが非アクティブ化された後は、テーブル名ではその履歴に対してクエリを実行できなくなります。

まず、システムカタログテーブルをクエリして、テーブル ID を見つけます。たとえば、次のクエリは `VehicleRegistration` テーブルの `tableId` を返します。

```
SELECT tableId FROM information_schema.user_tables
WHERE name = 'VehicleRegistration'
```

次に、この ID を使用して、[リビジョン履歴のクエリの実行](working.history.md) から同じ履歴クエリを実行できます。以下の例では、テーブル ID `5PLf9SXwndd63lPaSIa0O6`、ドキュメント ID `ADR2Ll1fGsU4Jr4EqTdnQF` の履歴に対してクエリを実行しています。テーブル ID は文字列リテラルであり、単一引用符で囲む必要があります。

```
--replace both the table and document IDs with your values
SELECT * FROM history('5PLf9SXwndd63lPaSIa0O6', `2000T`, `2019-06-05T23:59:59Z`) AS h
WHERE h.metadata.id = 'ADR2Ll1fGsU4Jr4EqTdnQF'
```

## テーブルを再アクティブ化
<a name="working.history.undrop-table"></a>

QLDB でテーブルを非アクティブ化したら、[テーブルの削除の取り消し](ql-reference.undrop-table.md) ステートメントを使用してテーブルを再度アクティブにすることができます。

まず、`information_schema.user_tables` からテーブル ID を見つけます。たとえば、次のクエリは `VehicleRegistration` テーブルの `tableId` を返します。ステータスは `INACTIVE` である必要があります。

```
SELECT tableId FROM information_schema.user_tables
WHERE name = 'VehicleRegistration'
```

次に、この ID を使用してテーブルを再度有効にします。以下に、テーブル ID `5PLf9SXwndd63lPaSIa0O6` の削除を取り消す例を示します。この場合、テーブル ID は、二重引用符で囲まれた一意の識別子です。

```
UNDROP TABLE "5PLf9SXwndd63lPaSIa0O6"
```

これで、`VehicleRegistration` のステータスが `ACTIVE` になります。

インデックスを作成、説明、および削除する方法については、[インデックスの管理](working.manage-indexes.md) に進んでください。

# インデックスの管理
<a name="working.manage-indexes"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

このセクションでは、Amazon QLDB でインデックスを作成、説明、削除する方法を説明します。作成できるテーブルあたりのインデックス数のクォータは、[Amazon QLDB でのクォータと制限](limits.md#limits.fixed) で定義されます。

**Topics**
+ [インデックスの作成](#working.manage-indexes.create)
+ [インデックスの説明](#working.manage-indexes.describe)
+ [インデックスの削除](#working.manage-indexes.drop)
+ [一般的なエラー](#working.manage-indexes.errors)

## インデックスの作成
<a name="working.manage-indexes.create"></a>

「[テーブルとインデックスの作成](working.create.md#working.create.tables-indexes)」でも説明したように、[CREATE INDEX](ql-reference.create-index.md) ステートメントを使用して、次のように、指定したトップレベルフィールドのテーブル上にインデックスを作成することができます。テーブル名とインデックス付きフィールド名は、大文字と小文字を区別します。

```
CREATE INDEX ON VehicleRegistration (VIN)
```

```
CREATE INDEX ON VehicleRegistration (LicensePlateNumber)
```

テーブルで作成する各インデックスには、システムによって割り当てられた一意の ID があります。このインデックス ID を検索するには、次のセクション「[インデックスの説明](#working.manage-indexes.describe)」を参照してください。

**重要**  
ドキュメントを効率的に検索するには、インデックスが必要です。インデックスがないと、QLDB はドキュメントを読み取るときにテーブルスキャンを実行する必要があります。これにより、同時実行の競合やトランザクションのタイムアウトなど、大きなテーブルでパフォーマンスの問題が発生する可能性があります。  
テーブルスキャンを回避するには、インデックス付きフィールドまたはドキュメント ID で**等価演算子 (`=` または `IN`) を使用する `WHERE` 述語句でステートメントを実行する必要があります。詳細については、「[クエリパフォーマンスの最適化](working.optimize.md)」を参照してください。

インデックスを作成する際には、以下の制約があることに注意してください。
+ インデックスは 1 つのトップレベルフィールドでのみ作成できます。複合、ネスト、一意、および関数ベースのインデックスはサポートされていません。
+ 任意の [Ion データ型](ql-reference.data-types.md) (`list`、`struct` など) でインデックスを作成できます。ただし、Ion のデータ型に関わらず、Ion 値全体の等価によってインデックス付けされたルックアップのみを実行できます。例えば、`list` 型をインデックスとして使用すると、リスト内の 1 つの項目でインデックス付けされたルックアップは実行できません。
+ クエリのパフォーマンスは、等価述語 (`WHERE indexedField = 123`、`WHERE indexedField IN (456, 789)` など) を使用する場合にのみ向上します。

  QLDB では、クエリの述語で不等式はサポートされていません。そのため、範囲でフィルタリングされるスキャンは実装されていません。
+ インデックス付きフィールドの名前は大文字と小文字の区別があり 128 文字以下で指定します。
+ QLDB でのインデックス作成は非同期です。空でないテーブルでのインデックスの作成を完了するのにかかる時間は、テーブルサイズによって異なります。詳細については、「[インデックスの管理](#working.manage-indexes)」を参照してください。

## インデックスの説明
<a name="working.manage-indexes.describe"></a>

QLDB でのインデックス作成は非同期です。空でないテーブルでのインデックスの作成を完了するのにかかる時間は、テーブルサイズによって異なります。インデックス構築のステータスを確認するには、システムカタログテーブル [information\$1schema.user\$1tables](working.catalog.md) のクエリを実行します。

例えば、次のステートメントは、`VehicleRegistration` テーブルのすべてのインデックスに対してシステムカタログのクエリを実行します。

```
SELECT VALUE indexes
FROM information_schema.user_tables info, info.indexes indexes
WHERE info.name = 'VehicleRegistration'
```

```
{
    indexId: "Djg2nt0yIs2GY0T29Kud1z",
    expr: "[VIN]",
    status: "ONLINE"
},
{
    indexId: "4tPW3fUhaVhDinRgKRLhGU",
    expr: "[LicensePlateNumber]",
    status: "FAILED",
    message: "aws.ledger.errors.InvalidEntityError: Document contains multiple values for indexed field: LicensePlateNumber"
}
```

**インデックスフィールド**
+ `indexId`: インデックスの一意の ID。
+ `expr`: インデックス付きドキュメントパス。このフィールドは、`[fieldName]` 形式の文字列です。
+ `status`: インデックスの現在のステータス。インデックスのステータスは以下のいずれかの値になります。
  + `BUILDING`: テーブルのインデックスをアクティブに構築しています。
  + `FINALIZING`: インデックスの構築が完了し、使用するためにアクティブ化を開始しています。
  + `ONLINE`: アクティブになっていて、クエリで使用できる状態です。QLDB は、ステータスがオンラインになるまで、クエリのインデックスを使用しません。
  + `FAILED`: 回復不能なエラーのため、インデックスを構築できません。この状態のインデックスは、テーブルあたりのインデックスのクォータにそのまま不利に作用します。詳細については、「[一般的なエラー](#working.manage-indexes.errors)」を参照してください。
  + `DELETING`: ユーザーがインデックスを削除した後、インデックスをアクティブに削除します。
+ `message`: インデックスに `FAILED` ステータスがある理由を説明するエラーメッセージ。このフィールドは、失敗したインデックスにのみ含まれます。

### コンソールを使用する
<a name="working.manage-indexes.describe.con"></a>

を使用してインデックスのステータス AWS マネジメントコンソール を確認することもできます。

**インデックスのステータスを確認するには (コンソール)**

1. にサインインし AWS マネジメントコンソール、[https://console.aws.amazon.com/qldb](https://console.aws.amazon.com/qldb) で Amazon QLDB コンソールを開きます。

1. ナビゲーションペイン内で [**Ledgers (台帳)**] を選択します。

1. **[Ledgers]** (台帳) リストで、インデックスを管理する台帳の名前を選択します。

1. 台帳の詳細ページの **[Tables]** (テーブル) タブで、インデックスを確認するテーブル名を選択します。

1. テーブルの詳細ページで、**[Indexed fields]** (インデックス付きフィールド) カードを見つけます。**[Index status]** (インデックス ステータス) 列に、テーブルの各インデックスの現在のステータスが表示されます。

## インデックスの削除
<a name="working.manage-indexes.drop"></a>

[DROP INDEX](ql-reference.drop-index.md) ステートメントを使用して、インデックスを削除します。インデックスを削除すると、テーブルから完全に削除されます。

まず、`information_schema.user_tables` からインデックス ID を見つけます。例えば、次のクエリは、`VehicleRegistration` テーブルでインデックス付き `LicensePlateNumber` フィールドの `indexId` を返します。

```
SELECT indexes.indexId
FROM information_schema.user_tables info, info.indexes indexes
WHERE info.name = 'VehicleRegistration' and indexes.expr = '[LicensePlateNumber]'
```

次に、この ID を使用してインデックスを削除します。以下は、インデックス ID `4tPW3fUhaVhDinRgKRLhGU` を削除する例です。インデックス ID は一意の識別子であり、二重引用符で囲まれています。

```
DROP INDEX "4tPW3fUhaVhDinRgKRLhGU" ON VehicleRegistration WITH (purge = true)
```

**注記**  
`WITH (purge = true)` 句はすべての `DROP INDEX` ステートメントに必要です。現在 `true` のみが値としてサポートされています。  
キーワード `purge` は大文字と小文字が区別され、すべて小文字にする必要があります。

### コンソールを使用する
<a name="working.manage-indexes.drop.con"></a>

を使用してインデックス AWS マネジメントコンソール を削除することもできます。

**インデックスを削除するには (コンソール)**

1. にサインインし AWS マネジメントコンソール、[https://console.aws.amazon.com/qldb](https://console.aws.amazon.com/qldb) で Amazon QLDB コンソールを開きます。

1. ナビゲーションペイン内で [**Ledgers (台帳)**] を選択します。

1. **[Ledgers]** (台帳) リストで、インデックスを管理する台帳の名前を選択します。

1. 台帳の詳細ページの **[Tables]** (テーブル) タブで、インデックスを削除するテーブル名を選択します。

1. テーブルの詳細ページで、**[Indexed fields]** (インデックス付きフィールド) カードを見つけます。削除するインデックスを選択し、**[Drop index]** (インデックスの削除) を選択します。

## 一般的なエラー
<a name="working.manage-indexes.errors"></a>

このセクションでは、インデックスの作成時に発生する可能性のある一般的なエラーについて説明し、考えられる解決策を提案します。

**注記**  
ステータスが `FAILED` のインデックスはそのままテーブルあたりのインデックスのクォータに不利に作用します。また、失敗したインデックスによって、テーブルでのインデックス作成が失敗した原因となったドキュメントの変更と削除はできません。  
明示的にインデックスを[削除](#working.manage-indexes.drop)してクォータから削除する必要があります。

**ドキュメントには、インデックス付きフィールド *fieldName* の複数の値が含まれています。**  
同じフィールドに対して複数の値があるドキュメントがテーブルに含まれている (つまり、フィールド名が重複する) ため、QLDB は指定したフィールド名にインデックスを構築することができません。  
まず、失敗したインデックスを削除する必要があります。次に、インデックスの作成を再試行する前に、テーブル内のすべてのドキュメントが各フィールド名に 1 つの値しか持たないことを確認してください。重複のない別のフィールドのインデックスを作成することもできます。  
QLDB は、テーブルで既にインデックス付けされているフィールドに対して複数の値を含むドキュメントを挿入しようとした場合も、このエラーを返します。

**Exceeded indexes limit: Table *tableName* already has *n* indexes, and cannot create more. (インデックスの制限を超えました: 既にテーブル tableName には n インデックスがあり、これ以上作成することはできません。)**  
QLDB では、失敗したインデックスを含めて、テーブルあたりに 5 つのインデックスの制限が適用されます。新しいインデックスを作成する前に、既存のインデックスを削除する必要があります。

**No defined index with identifier: *indexId*. (識別子 IndexID を持つ定義済みのインデックスがありません。)**  
指定したテーブルとインデックス ID の組み合わせに存在しないインデックスを削除しようとしました。既存のインデックスを確認する方法については、「[インデックスの説明](#working.manage-indexes.describe)」を参照してください。

# Amazon QLDB で割り当てられる一意の ID
<a name="working.unique-id"></a>

**重要**  
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了まで Amazon QLDB を使用できます。詳細については、[「Amazon QLDB 台帳を Amazon Aurora PostgreSQL に移行する](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)」を参照してください。

このセクションでは、Amazon QLDB のシステム割り当て一意 ID のプロパティと使用ガイドラインについて説明します。また、QLDB の一意な ID の例をいくつか示します。

**Topics**
+ [プロパティ](#working.unique-id.properties)
+ [使用方法](#working.unique-id.usage)
+ [例](#working.unique-id.examples)

## プロパティ
<a name="working.unique-id.properties"></a>

QLDB では、システムによって割り当てられた ID はすべて、汎用一意 ID (UUID、Universally Unique Identifier) です。各 ID には次のプロパティがあります。
+ 128 ビットの UUID 番号
+ Base62 でエンコードされたテキストで表される
+ 22 文字の固定長の英数字の文字列 (例: `3Qv67yjXEwB9SjmvkuG6Cp`)。

## 使用方法
<a name="working.unique-id.usage"></a>

アプリケーションで QLDB の一意の ID を使用する場合は、次のガイドラインに注意してください。

**Do**
+ ID は文字列として扱います。

**しません**
+ 文字列をデコードする。
+ セマンティックな意味を文字列に帰する (時間コンポーネントの取得など)。
+ 文字列をセマンティック順に並べ替える。

## 例
<a name="working.unique-id.examples"></a>

次の属性は、QLDB の一意の ID の例です。
+ ドキュメント ID
+ インデックス ID
+ ストランド ID
+ テーブル ID
+ トランザクション ID