インデックスを管理するときのリレーショナル (SQL) データベースと DynamoDB の相違点 - Amazon DynamoDB

インデックスを管理するときのリレーショナル (SQL) データベースと DynamoDB の相違点

インデックスは代替のクエリパターンへのアクセスを付与し、クエリを高速化できます。このセクションでは、SQL と Amazon DynamoDB におけるインデックスの作成と使用を比較します。

リレーショナルデータベースまたは DynamoDB のいずれを使用するにしても、インデックスの作成は慎重に判断する必要があります。テーブルに書き込みが発生するたびに、テーブルのインデックスはすべて、更新する必要があります。大きなテーブルでの書き込み量が多い環境では、大量のシステムリソースを消費する可能性があります。読み取り専用または読み取りがほとんどの環境では、これは大きな問題にはなりません。ただし、インデックスがアプリケーションによって実際に使用されており、ただ容量を取っていることがないよう確認する必要があります。

インデックス作成時のリレーショナル (SQL) データベースと DynamoDB の相違点

SQL の CREATE INDEX ステートメントを Amazon DynamoDB の UpdateTable オペレーションと比較します。

SQL を使ってインデックスを作成する

リレーショナルデータベースのインデックスは、テーブルの異なる列に対して高速にクエリを実行できるデータ構造です。CREATE INDEX SQL ステートメントを使用して、既存のテーブルにインデックスが追加し、インデックスを作成する列を指定します。インデックスの作成後は、通常どおりテーブルのデータにクエリを実行できますが、テーブル全体をスキャンする代わりに、テーブルの指定された行を迅速に検索するため、データベースがインデックスを使用することができます。

インデックスの作成後は、データベースが維持します。テーブルのデータを変更した場合は、インデックスが自動的に変更され、テーブル内の変更を反映します。

MySQL では、次のようなインデックスを作成します。

CREATE INDEX GenreAndPriceIndex ON Music (genre, price);

DynamoDB でインデックスを作成する

DynamoDB では、同様の目的のために、セカンダリインデックスを作成して使用できます。

DynamoDB のインデックスはリレーショナルな対応物とは異なります。セカンダリインデックスを作成する際、そのキー属性 (パーティションキーとソートキー) を指定する必要があります。セカンダリインデックスを作成したら、テーブルと同じように Query または Scan を実行できます。DynamoDB にはクエリオプティマイザーがないため、セカンダリインデックスは Query または Scan の場合にのみ使用されます。

DynamoDB では、次の 2 種類のインデックスをサポートしています。

  • グローバルセカンダリインデックス – インデックスのプライマリキーは、テーブルからの任意の 2 つの属性になります。

  • ローカルセカンダリインデックス – インデックスのパーティションキーは、テーブルのパーティションキーと同じである必要があります。ただし、ソートキーは、他の任意の属性にすることができます。

DynamoDB を使えば、セカンダリインデックスのデータは結果的にテーブルと整合性が取れます。テーブルまたはローカルセカンダリインデックスでの強い整合性を持つ Query または Scan オペレーションをリクエストできます。ただし、グローバルセカンダリインデックスは結果整合性のみをサポートします。

UpdateTable オペレーションを使用し、GlobalSecondaryIndexUpdates を指定して、既存のテーブルにグローバルセカンダリインデックスを追加できます。

{ TableName: "Music", AttributeDefinitions:[ {AttributeName: "Genre", AttributeType: "S"}, {AttributeName: "Price", AttributeType: "N"} ], GlobalSecondaryIndexUpdates: [ { Create: { IndexName: "GenreAndPriceIndex", KeySchema: [ {AttributeName: "Genre", KeyType: "HASH"}, //Partition key {AttributeName: "Price", KeyType: "RANGE"}, //Sort key ], Projection: { "ProjectionType": "ALL" }, ProvisionedThroughput: { // Only specified if using provisioned mode "ReadCapacityUnits": 1,"WriteCapacityUnits": 1 } } } ] }

UpdateTable に以下のパラメータを提供する必要があります。

  • TableName – インデックスが関連付けられるテーブル。

  • AttributeDefinitions – インデックスのキースキーマ属性用のデータ型。

  • GlobalSecondaryIndexUpdates – 作成するインデックスに関する詳細。

    • IndexName – インデックスの名前。

    • KeySchema – インデックスのプライマリキーに使用する属性。

    • Projection – テーブルからインデックスにコピーされる属性。この場合、ALL は、すべての属性がコピーされることを意味します。

    • ProvisionedThroughput (for provisioned tables) – このインデックスに必要な 1 秒あたりの読み取り/書き込み数。(これは、テーブルのプロビジョニングされたスループット設定とは異なります。)

このオペレーションの一部は、テーブルから新しいインデックスにデータをバックフィリングすることを含みます。バックフィリング中、テーブルは使用可能なままになります。ただし、インデックスは Backfilling 属性が true から false に変わるまで、準備ができていません。DescribeTable オペレーションを使用して、この属性を表示できます。

インデックスのクエリとスキャン時のリレーショナル (SQL) データベースと DynamoDB の相違点

SQL の SELECT ステートメントを使用したインデックスのクエリとスキャンを Amazon DynamoDB の Query および Scan オペレーションと比較します。

SQL を使ってインデックスのクエリを実行してスキャンする

リレーショナルデータベースでは、インデックスを直接使用しません。代わりに、SELECT ステートメントの発行により、テーブルでクエリを実行し、クエリオプティマイザは任意のインデックスを利用できます。

クエリオプティマイザは、使用できるインデックスを評価し、クエリを高速化するためにそれらを使用できるかを決定するリレーショナルデータベース管理システム (RDBMS) のコンポーネントです。クエリを高速化するためにインデックスが使用できる場合、RDBMS は最初にインデックスにアクセスし、それを使用してテーブルのデータを特定します。

GenreAndPriceIndex を使用してパフォーマンスを向上できる SQL ステートメントを次に示します。ここでは、Music テーブルに十分なデータがあり、クエリオプティマイザが、テーブル全体にスキャンするのではなく、このインデックスを使用することを前提にします。

/* All of the rock songs */ SELECT * FROM Music WHERE Genre = 'Rock';
/* All of the cheap country songs */ SELECT Artist, SongTitle, Price FROM Music WHERE Genre = 'Country' AND Price < 0.50;

DynamoDB でインデックスのクエリを実行してスキャンする

DynamoDB では、テーブルに対して実行するのと同じように、インデックスに対して直接 Query および Scan オペレーションを実行します。DynamoDB API または PartiQL (SQL 互換のクエリ言語) を使用して、インデックスにクエリやスキャンを実行できます。TableNameIndexName の両方を指定する必要があります。

以下は、DynamoDB の GenreAndPriceIndex に対するいくつかのクエリです。(このインデックスのキースキーマは、ジャンル価格で構成されています。)

DynamoDB API
// All of the rock songs { TableName: "Music", IndexName: "GenreAndPriceIndex", KeyConditionExpression: "Genre = :genre", ExpressionAttributeValues: { ":genre": "Rock" }, };

この例では ProjectionExpression を使用して、属性すべてではなく、一部のみを結果に表示することを示します。

// All of the cheap country songs { TableName: "Music", IndexName: "GenreAndPriceIndex", KeyConditionExpression: "Genre = :genre and Price < :price", ExpressionAttributeValues: { ":genre": "Country", ":price": 0.50 }, ProjectionExpression: "Artist, SongTitle, Price" };

次に示すのは、GenreAndPriceIndex に対するスキャンです。

// Return all of the data in the index { TableName: "Music", IndexName: "GenreAndPriceIndex" }
PartiQL for DynamoDB

PartiQL では、Select ステートメントを使用して、インデックスに対してクエリとスキャンを実行します。

// All of the rock songs SELECT * FROM Music.GenreAndPriceIndex WHERE Genre = 'Rock'
// All of the cheap country songs SELECT * FROM Music.GenreAndPriceIndex WHERE Genre = 'Rock' AND Price < 0.50

次に示すのは、GenreAndPriceIndex に対するスキャンです。

// Return all of the data in the index SELECT * FROM Music.GenreAndPriceIndex
注記

Select を使用したコード例については、「DynamoDB 用の PartiQL select ステートメント」を参照してください。