どうも、AWS勉強中のとがみんです。
改竄がされていないことを証明したいデータを管理するために、台帳データベースを実際に使っていくにあたって、台帳に保存されたデータを集計したいと考えた時に、検索のパフォーマンスについて気になったので調べてみることにしました。
QLDBのデータ構造と、SQLlikeに実行できるPartiQLについての整理とクエリ最適化について整理していきます。
Contents
QLDBのデータ構造とPartiQL
QLDBのデータ構造
Amazon QLDBは、データレコードを「ドキュメント」として保存され、それはAmazon Ionというstruct型のオブジェクトです。そのオブジェクトがテーブルに挿入されます。
Amazon Ionの具体例は以下のようなものです。
1 2 3 4 5 6 7 8 9 | { ID: "12345", Name: "togamin", City: "Kyoto", Hobby: [ {name:"Programing",detail:"サービス開発をすること"}, {name:"Aquarium",detail:"魚を眺めること"} ] } |
QLDBドキュメントは「名前」と「値」のペアで構成され、struct型のオブジェクトは{}で表現されlist型は[]で表現されます。
PartiQL
QLDBに格納されたデータは、PartiQLというSQLを拡張したクエリ言語を活用してデータリソースへのアクセスを行うことができます。
PartiQLは、リレーショナル形式のデータベースだけでなく、Key Value Storeや、JSON形式のNpSQLデータベース、CSVファイルなど、様々なデータソースに対して、同じ構文で問い合わせることができます。
QLDBで管理されているIon構造のデータに対してもPartiQLというクエリ言語を活用してSQLライクにデータアクセスできます。
PartiQLとIon型のマッピング
Ionのstruct型は、SQLのタプル型と同等のものです。
タプルとはリレーショナルデータベースにおいて、テーブルの行にあたるものです。
QLDBに下記のデータ構造のドキュメントを挿入し、クエリとその実行結果について確認していきます。
SELECT文で挿入したドキュメントを確認しました。
Amazon Ion型のJSONは上記のようなテーブルとして表現されます。
Hobbyにリストとして要素が複数入っているので、その中身を参照してみます。
さらにリストの一つの要素の中の値を取得します。
このようにAmazon Ion型のデータとSQLライクなPartiQLがマッピングされます。
QLDBへのクエリパフォーマンス
Amazon QLDBは、オンライントランザクション処理ワークロードのニーズに対応することを目的としています。そのため、SQLのようなクエリ機能をサポートしているが、特定のクエリパターンに最適化されています。
特定のクエリパターン以外だと、クエリはテーブル全体のスキャンを呼び出してしまい、クエリのレイテンシー、トランザクションのタイムアウト、同時実行による競合など、パフォーマンス上の問題が発生してしまいます。
そのため最適なクエリパターンに沿ってクエリ実行することが推奨されています。
オンライントランザクション処理:処理要求があるとホストコンピューターが即座に処理応答する方式。
レイテンシー:要求されたリソースが目的値に到達するまでにかかるネットワーク時間。
最適なクエリパターン例
パフォーマンス上最適な検索を行うためには、カーディナリティが高いフィールドにインデックスを作成し、そのフィールド、またはドキュメントIDでフィルタリングすることが推奨されています。
カーディナリティ:カラムに格納されているデータの種類がどのくらいあるのかをカーディナリティといい、データの種類が少ない場合はカーディナリティが低いといい、多い場合はカーディナリティが高いという。
以下に具体例を整理しています。
インデックス付き高カーディナリティフィールドでの検索
WHERE VIN = ‘1N4AL11D75C109151’
インデックス付き高カーディナリティフィールドと別フィールドでの検索
WHERE VIN = ‘1N4AL11D75C109151’ AND City = ‘Seattle’
IN句を活用した、インデックス付高カーディナリティフィールドでの検索
WHERE VIN IN (‘1N4AL11D75C109151’, ‘KM8SRDHF6EU074761’)
BY句を使用したドキュメントIDでの検索
WHERE r_id = ‘3Qv67yjXEwB9SjmvkuG6Cp’
回避すべきクエリパターン
パフォーマンスが問題になってしまうクエリパターンとしては、低カーディナリティでの検索や、検索条件をつけないクエリが挙げられます。パフォーマンスだけでなく、テーブル全体スキャンを呼び出してしまい、トランザクションタイムアウトや同時実行による競合を呼び出してしまうため、避ける必要があります。
下記が推奨されないクエリのパターンです。
WHERE句のないクエリ
COUNT()関数
低カーディナリティでの検索
不等式はインデックス付きの検索対象にならない
LIKE句によるテキスト検索
BETWEEN句による検索
WHERE ValidToDate BETWEEN
2020-01-01T
AND 2020-07-01T
ドキュメントIDと検索対象期間のない履歴クエリ
まとめ
QLDBのデータ構造とPartiQLについて、また、クエリ実行に関して、最適化のためのクエリパターンや回避すべきクエリパターンについて整理しました。