Aurora DSQLの制約を知ってより理解を深める

Aurora DSQLの制約を知ってより理解を深める

Amazon Aurora DSQLの制約と特徴についてまとめました。通常のPostgreSQLと異なり、サポート外のデータ型、DDLとDMLの同一トランザクション不可、データを含むテーブルのCREATE INDEX等多くの制約がありますが、これらの制約を理解することでよりAurora DSQLの理解を深めるきっかけとなれば幸いです。
Clock Icon2024.12.19

「制約を知れば知るほど、もっとそのテクノロジーへの愛が深まる…」

以前こんなツイートしたところ、いくらか反応がありました。

https://x.com/hamako9999/status/1867876144886018242

re:Invent 2024におけるAurora DSQLの発表はかなりのインパクトがあったのですが、ドキュメントを見れば見るほど、これは従来のAurora(PostgreSQL)とはかなり違うなぁという印象を持つ人も多いと思います。自分も思いました。

最速のサーバーレス分散SQLデータベース「Aurora DSQL」。トランザクション制御の方式も楽観同時実行制御がベースとなっていたり独特で、かつ通常のPostgreSQLとはコマンドレベルでは、かなり違う(制約がある)部分も見えてきました。

このブログでは、Aurora DSQLの制約(できないこと)を中心に情報をまとめています。まだプレビューのAurora DSQLですが、この制約を知っておくことで、逆にAurora DSQLの使い所や特徴が浮かび上がってきます。

まだ現在はAurora DSQLの利用に料金がかかりません。今のうちにあれこれさわってみつつ、実運用を見据えた時にどのような制約がありそうか体験してみるのも良いと思います。

ほな、いってみよ!!

免責事項

関連資料

Aurora DSQLのアーキテクチャに関する資料

Aurora DSQLがなにでどういった特徴とアーキテクチャをもっているのかを紹介した資料。制約と合わせて改めてこちらを見てもらえれば、理解深まると思います。

Aurora DSQLの制約に関連する情報がまとまっている資料

どんなコマンドがサポート外か、PostgreSQLとの差分は何なのかなどの情報は、基本ユーザーガイドに全てまとまっています。この後、このドキュメントを参考にしながら、できない点を深ぼっていきます。

What is Amazon Aurora DSQL? - Amazon Aurora DSQL

Aurora DSQLで利用できるPostgreSQLプロトコル

以下、サポートされているプロトコルと制約についての記載があるドキュメントです。

Using the PostgreSQL protocol with Aurora DSQL - Amazon Aurora DSQL

独自ロールの作成について

Aurora DSQLはadminという名前のロールを作成します。カスタムデータベースロールを作成する場合は、クラスターへの接続時に認証を行うために、IAMロールと関連付けるためにadminロールを使用する必要があります。詳細はこちらUsing database roles with IAM roles - Amazon Aurora DSQL

作成できるDatabaseについて

クラスタ内に作成できるデータベースは、postgresのみ。このデータベースは、最初のクラスター作成時に自動的に作成されます。他のデータベースの作成はできません。この通りエラーになります。

create database hamako;

SQLエラー [0A000]: ERROR: unsupported statement: Createdb

DB接続時のパスワード

長期間有効なパスワードはなく、一時的な認証トークンを利用して接続します。詳細はこちら。

Generating an authentication token in Amazon Aurora DSQL - Amazon Aurora DSQL

冒頭、DeepLによる翻訳。

お好みの SQL クライアントで Amazon Aurora DSQL に接続するには、パスワードとして使用する認証トークンを生成する必要があります。デフォルトでは、AWSコンソールを使用して作成した場合、これらのトークンは自動的に1時間で期限切れになります。AWS CLIまたはSDKを使用してトークンを作成した場合、デフォルトは15分です。最大値は604,800秒、つまり1週間です。クライアントからAurora DSQLに再度接続するには、トークンが期限切れになっていなければ同じトークンを使用できますが、新しいトークンを生成することもできます。

と記載があるとおり、トークンには有効期限があります。実際にアプリケーションで使う場合にどう実装するかは、公式ドキュメントの各ライブラリのサンプルコードを参照してください。

PostgreSQLのデータ型サポート有無

Supported data types in Aurora DSQL - Amazon Aurora DSQL

上記ページに、サポートされているデータ型とAurora DSQL独自のLimitについて記載されています。逆に、上記ページに記載されていないデータ型は基本的に使えないと考えて良さそうです。

私が見かけた範囲でサポート外のものとして代表的なのがSERIALデータ型,IDENTITY制約です。例えば、以下のCREATE TABLE文はエラーとなります。

create table sample_tbl(
    choice_no smallint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    quantity int,
    number bigint,
    price numeric(10,3),
    u_id serial,
    product_name varchar(10),
    product_id char(5),
    remarks text,
    create_date timestamp(3), 
    open_date date,
    open_time time(3),
    delete_flg boolean
);

SQLエラー [42704]: ERROR: type "serial" does not exist

また、IDENTITY制約も以下の通りエラーとなります。

create table sample_tbl(
    choice_no smallint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
);

SQLエラー [0A000]: ERROR: IDENTITY constraint is not supported

主キーの整数型を自動増分で設定したい時にSERIALデータ型を使う場合も多いと思いますが、そもそもAurora DSQLではサポート外なので要注意です。

またIDENTITY制約については、以下の記事でやまたつが記載しているような罠もでてくると思うので、運用含めた事前検証は必ずやっておきましょう。

Aurora DSQLにdrizzleでLambdaからmigrationしてみた | DevelopersIO

PostgreSQLの機能でAurora DSQLでは明示的にサポートしていないもの

Unsupported PostgreSQL features in Aurora DSQL - Amazon Aurora DSQL

ここに、Aurora DSQLにおける主要な制約(できないこと)がまとめられています。表形式でまとめてみました。

カテゴリ 未サポート項目
Unsupported objects • Databases - Aurora DSQLは現時点でクラスターあたり1つのデータベースのみをサポート
• Views
• Temporary Tables
• Triggers
• Types
• Tablespaces
• UDFs / Functions(language = SQLの関数以外)
• Sequences
Unsupported constraints • Foreign keys
• Exclusion constraints
Unsupported operations • ALTER SYSTEM
• TRUNCATE
• VACUUM
• SAVEPOINT
Unsupported extensions Aurora DSQLは現時点でPostgreSQLの拡張機能をサポートしていません。以下の主要な拡張機能は未サポートです:
• PL/pgSQL
• PostGIS
• PGVector
• PGAudit
• Postgres_FDW
• PGCron
• pg_stat_statements

オブジェクトに関しては、先述したpostgres以外のCREATE DATABASEVIEW,TRIGGER,TABLESPACE,SEQUENCEなどがサポート外。それ以外にも、外部キー制約FOREIN KEY,TRUNCATEなどもサポートしていません。

また、Extensionsも多くがサポート外となっています。

Unsupported SQL Expressionsには、CREATE INDEX(if table has date)もサポート外であることが記載されています。これもきつい制約ではありますが、テーブルにデータが含まれている時のインデックス作成手段として、CREATE INDEX ASYNCがAurora DSQL独自でサポートされています(後述)。

データが有るときのCREATE INDEXはサポート外のため、CREATE INDEX ASYNCの利用が必要

Aurora DSQLにおいては、CREATE INDEXはテーブルにデータが無い時だけ実行でき、データが有るときはエラーとなります。以下に簡単な例で見てみます。

CREATE TABLE employees (
    id INT PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    department VARCHAR(50),
    hire_date DATE,
    salary INTEGER
);
INSERT INTO employees (id, first_name, last_name, email, department, hire_date, salary)
VALUES
    (1, '山田', '太郎', 'yamada.taro@example.com', '営業部', '2020-04-01', 350000),
    (2, '佐藤', '花子', 'sato.hanako@example.com', '人事部', '2021-04-01', 320000),
    (3, '鈴木', '一郎', 'suzuki.ichiro@example.com', '技術部', '2019-10-01', 400000),
    (4, '田中', '美咲', 'tanaka.misaki@example.com', '営業部', '2022-04-01', 300000);

データが有るときは、CREATE INDEXはエラー

テーブルにデータが含まれているときは、CREATE INDEXは失敗します。

select count(*) from employee;
count|
-----+
    4|

CREATE INDEX idx_employees_email ON employees(email);
SQLエラー [0A000]: ERROR: adding an index on a table that already has data is not supported yet

データが無いときは、CREATE INDEXは正常に実行可能

データ削除後であれば、Create Indexは可能。

delete from employees;
select count(*) from employee;
count|
-----+
    0|

CREATE INDEX idx_employees_email ON employees(email);
select tablename, indexname from pg_indexes where tablename = 'employees';

tablename|indexname          |
---------+-------------------+
employees|employees_pkey     |
employees|employees_email_key|
employees|idx_employees_email|

次の検証に入るため、INDEXを削除しておきます。データが有る状態でのDROP INDEXは対応している模様。

drop index idx_employees_email;

データが有るときは、Aurora DSQL固有のCREATE INDEX ASYNCを利用する

CREATE INDEX ASYNCについての公式マニュアルはこちら。

https://docs.aws.amazon.com/aurora-dsql/latest/userguide/working-with-create-index-async.html

通常のCREATE INDEXの後ろにASYNCを付加するだけで、それ以外は基本的に通常のCREATE INDEXとの大きな違いは無さそうです。

CREATE INDEX ASYNC idx_employees_email ON employees(email);
job_id                    |
--------------------------+
abedvjhxvnbybm7idq3s7ago3i|

レスポンスに見慣れない、job_idなるものが返ってきました。これが、Aurora DSQLのCREATE INDEX ASYNC固有のもので、インデックス作成中にこのジョブの状態を監視することで、ジョブが完了するか失敗するまでセッションをブロックすることができるようです。

以下、マニュアルからの引用。専用のsys.wait_for_job(job_id)sys.cancel_job(job_id)プロシージャが用意されており、それを利用してセッションをブロックすることができる

Aurora DSQL also supports the procedures sys.wait_for_job(job_id) and sys.cancel_job(job_id). sys.wait_for_job lets you block the session until the specified job completes or fails. This procedure returns a Boolean. sys.cancel_job lets you cancel an asynchronous job that is in progress.

試しにwait_for_jobプロシージャを実行すると、以下のレスポンスが返ってきました。既に完了してるってことすね。はい。

CALL sys.wait_for_job('abedvjhxvnbybm7idq3s7ago3i');

Job execution succeeded for job with id abedvjhxvnbybm7idq3s7ago3i

上記のCREATE INDEX ASYNCを実行後、sysスキーマ内のjobsビューに以下の値が反映されていました。

select * from sys.jobs;

job_id                    |status   |details|
--------------------------+---------+-------+
abedvjhxvnbybm7idq3s7ago3i|completed|       |

statuscompletedになっているので、既にインデックスの構築が完了していることを表しているようです。もともとテストデータ4件とかですからね。これがもっと大量のテーブルへのインデックス作成であれば、このビューを見ることで、インデックス作成のステータスを確認できるとのことです。

このあたりのDSQL独自のシステムビューについては、以下の公式ドキュメントに記載があるので、併せて参考にしてもらえれば。インデックス作成中であれば、statusprocessingと表示されるようです。

https://docs.aws.amazon.com/aurora-dsql/latest/userguide/working-with-systems-tables.html

トランザクション制御に楽観的同時実行制御を採用

通常リレーショナルデータベースでは採用されない、楽観的同時実行制御が採用されています。対象のユーザーガイドはこちら。

Understanding concurrency control in Aurora DSQL - Amazon Aurora DSQL

なのですが、こちらには、SELECT FOR UPDATEによるライトスキューの管理などが記載されておらず、そのあたりは、こちらの公式ブログに記載されています。

Amazon Aurora DSQL の同時実行制御 | Amazon Web Services ブログ

通常、ユーザーガイドで情報が不足していることは無いので、このユーザーガイドも現時点ではまだ発展途上なのかもしれません。

DDLとDMLを1トランザクションで実行できない

Aurora DSQLにはプライマリーデータベースノードやリーダーが存在しないため、データベースカタログは分散されており、スキーマの変更は分散トランザクションとして管理されています。そのため、DDLの動作が通常のPosgreSQLとは異なります。

具体的に言うと、DDLとDMLを一つのステートメントで実行しようとすると、エラーとなります。

BEGIN;
CREATE TABLE FOO (ID_col integer);
INSERT into FOO VALUES (1);

SQLエラー [0A000]: ERROR: ddl and dml are not supported in the same transaction

自分が実際ハマった具体例としては、テーブルにサンプルのデータを挿入するクエリ実行時に、CREATE TABLE後にINSERTしたクエリを実行しようとして上記エラーとなりました。世の中にあるサンプルデータ挿入クエリは概ねそのような構成になっているものが多いと思うので、そのあたりも注意が必要です。

主キーの設定に関して独自の考慮が必要

Primary keys in Aurora DSQL - Amazon Aurora DSQL

Aurora DSQLの内部構造を考慮した主キー戦略が解説されています。冒頭のこの部分をまずは、頭にいれておくのが良いでしょう。

DeepLによる翻訳。

Aurora DSQLでは、テーブルの主キーを定義することは、PostgreSQLのCLUSTER操作や他のデータベースシステムのクラスタ化インデックスに似ています。Aurora DSQLは、すべての列を参照するINCLUDEステートメントを適用し、インデックスで構成されたテーブルを作成します。この構造により、Aurora DSQLの主キーに対するすべての参照は、キーに関連付けられたすべての列の値にアクセスでき、データは常に主キーに従って順序付けられます。CLUSTER操作とは異なり、Aurora DSQLは常にこのインデックスで構成されたテーブルの順序を維持します。

Aurora DSQLは、この主な概念を使用して分散データ管理を構成します。Aurora DSQLは、プライマリキーを使用して、各テーブルまたはインデックスの各行に割り当てられるクラスター全体で一意のキーを構築します。Aurora DSQLは、このキーを使用してストレージを自動的にパーティショニングします。このパーティショニングキーは、Aurora DSQLの自動スケーリングおよび同時実行制御メカニズムにおいて中心的な役割を果たします。

後続の箇条書きに具体的な注意ポイントが記載されています。書き込みが多いテーブルで、単調に増加する整数をプライマリキーとして使用することは避けランダム性をもたせることで、ストレージパーティションを分散させることができるとのことです。

サポートされていないシステムテーブルが多数ある

Using system tables and commands in Aurora DSQL - Amazon Aurora DSQL

Aurora DSQLにおいては、PostgreSQLで利用できるシステムテーブルのうちサポートされていないものが多数あります。

上記公式ドキュメントの後半にシステムカタログテーブルシステムビューのうち、対応の有無が全て記載されているので、参考にしてください。

ロックの状態を確認するpg_locksなども対象外です。ただ、これらサポート対象外のシステムビューも、SQLを実行するとエラーにはならず、内容が空白になっていることは注意しておきましょう。エラーにならないため、サポートされているのかどうかが逆にわかりにくいと思います。

サポート対象外のシステムビューは、中身が空で返ってくる。

select * from pg_locks;

locktype|database|relation|page|tuple|virtualxid|transactionid|classid|objid|objsubid|virtualtransaction|pid|mode|granted|fastpath|waitstart|
--------+--------+--------+----+-----+----------+-------------+-------+-----+--------+------------------+---+----+-------+--------+---------+

制約を知ることで、よりAurora DSQLへの理解が深まる

以上、公式ドキュメントを紐解きながら、筆者の主観で代表的な制約(PostgreSQLとは違う点)をまとめてみました。Aurora DSQLは、Auroraのブランドが付いていますが、アーキテクチャもトランザクション制御もユースケースも従来のAurora(PostgreSQL)とはかなり異なると言っていいでしょう。

アーキテクチャを知り制約を知ることで、よりユースケースに沿ったAurora DSQLの使い道が見えてくると思います。このブログが何らかの参考になれば幸いです。まだプレビューのAurora DSQL。料金かからないので、今のうちにたんまり触っておきましょう!

それでは、今日はこのへんで。濱田孝治(ハマコー)(@hamako9999)でした。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.