ScalarDB Analytics with PostgreSQLをリリースしました

Akihiro Okuno
Scalar Engineering (JA)
15 min readAug 17, 2023

先日リリースされたScalarDB 3.9において、ScalarDBが管理するデータベース上で統一的に分析クエリを実現するScalarDB Analytics with PostgreSQLが新たに導入されました。本記事ではScalarDB Analytics with PostgreSQLの概要や利用方法などについて解説します。

ScalarDB Analytics with PostgreSQLとは?

ScalarDBは汎用的なトランザクションマネージャであり、RDBMSやNoSQL等を含む様々なデータベースの上で、複数のデータベースをまたいだトランザクション処理を実行することを可能とします。ScalarDBは多数のシンプルなトランザクションを処理するようなワークロードを主な対象としており、サポートしている操作はキーに基づいたCRUDや一部のScanのみに限られています。ScalarDBがサポートしている操作の一覧についてはAPIガイドをご参照ください。これらの制限のため、従来のScalarDBでは、ScalarDBが管理しているデータを用いたアドホックな分析など、より高度な処理を行いたい場合には、ユーザがアプリケーション側で独自に結合や集合処理などの実装を行う必要がありました。

ScalarDB Analytics with PostgreSQLは、ScalarDB管理下にあるデータベースに対して結合や集計を含む広範なクエリの実行をサポートし、アドホック分析などの高度な処理を行うことを可能にするために導入されたものです。ScalarDB Analytics with PostgreSQLは、名前が示す通り、ScalarDBが管理しているデータに対して、PostgreSQLを用いてクエリの実行を行うものとなっており、ユーザはPostgreSQLがサポートしている多様なクエリ処理を実行することが可能となります。また、ScalarDB Analytics with PostgreSQLでは、ScalarDB側で書き込んだデータをETL処理などを行わずにそのまま読み込めるようにするために、PostgreSQLを通してScalarDBが管理しているデータベースからデータを直接読み取ようになっています。この読み取りには、PostgreSQL本体が提供するForeign Data Wrapper(FDW)と呼ばれる外部データを扱うためのフレームワークを利用しています。

ScalarDBとScalarDB Analytics with PostgreSQLの関係を図示すると次のようになります。ユーザはScalarDBを通してこれまで通りにデータを読み書きしながら、高度なクエリを実行したい場合には、ScalarDB Analytics with PostgreSQLにクエリを投げることができます。ScalarDB Analytics with PostgreSQLはFDWを通して、ScalarDB管理下のデータベースから直接データを読み取るため、ScalarDB側で書き込んだデータは、追加の操作が必要とせずに、そのままScalarDB Analytics with PostgreSQLでも読み取りが可能です。

ScalarDB Analytics with PostgreSQLの概要

ScalarDB Analytics with PostgreSQLにはいくつか制限があります。第一に、ScalarDB Analytics with PostgreSQLでは読み取り操作のみがサポートされています。PostgreSQL本体ではもちろん書き込み操作もサポートされていますが、FDWを通したScalarDB管理下のデータベースへの書き込みを行うことができないため、INSERTなどのコマンドを実行しようとするとエラーになります。第二に、ScalarDB Analytics with PostgreSQLを通した読み込みで保証される分離レベルはRead-Committedになります。ScalarDBからの読み書きでは最も強い分離レベルであるSerializableが保証されますが、ScalarDB Analytics with PostgreSQLから読み込んだデータはRead-Committed、すなわち読み取りで取得した行は、いずれかのトランザクションでコミットされたものであることは保証されますが、取得した結果にはRead-skewなどのanomalyが含まれている可能性があります。

ScalarDB Analytics with PostgreSQLの仕組みは?

ScalarDB Analytics with PostgreSQLのアーキテクチャは以下のようになっています。

ScalarDB Analytics with PostgreSQLのアーキテクチャ

一番下がScalarDBが管理しているデータベースです。これらに書き込まれたデータをPostgreSQLから読み込むために、ScalarDB Analytics with PostgreSQLではFDWを利用しています。多くのFDWの実装がコミュニティによって提供されており、ScalarDB Analytics with PostgreSQLの内部ではjdbc_fdwcassandra_fdwなどを利用しています。しかし、ScalarDBでは多数のデータベースをサポートしているため、DynamoDBなどの既存のFDWでは対応できないものが存在します。ScalarDB Analytics with PostgreSQLでは、これらのデータベースからの読み込みをサポートするために、scalardb_fdwを新たに開発し利用しています。scalardb_fdwではJava Native Interfaceを用いて、FDWの内部においてScalarDBをライブラリとして直接利用し、ScalarDBのScan操作によって外部データベースのデータを読み込みます。scalardb_fdwはScalarDBを直接利用してデータを読み込んでいるため、必然的にScalarDBがサポートしているデータベースの全てをサポートすることが可能です。既存のFDWが存在するデータベースについては、データを読み込むためのFDWについて、既存のFDWとscalardb_fdwを含む複数の選択肢が存在することになりますが、ScalarDB Analytics with PostgreSQLでは、後述するSchema Importerによって、どのFDWを利用するかを自動的に決定して設定を行うため、ユーザはどのFDWを利用するかを意識する必要はありません。

PostgreSQLでは外部テーブル(Foreign Table)を定義することによって、FDWを通して読み取ったデータをPostgreSQL上のテーブルのデータとして扱うことができるようになります。ScalarDB Analytics with PostgreSQLでは、ScalarDB上で定義されたテーブル一つごとに、一つの外部テーブルを作成します。これらの外部テーブルは、ユーザがテーブルに定義した列に加えて、ScalarDBが内部的に利用するWALメタデータの列も同時に含むようにします。これらのWALメタデータの列は、次に説明するWAL-Interpreted Viewにおいて利用されます。

WAL-Interpreted Viewは、PostgreSQLのビューとして定義され、一つの外部テーブルごとに、一つのWAL-Interpreted Viewが作成されます。WAL-Interpreted Viewは、1. 外部テーブルに存在するWALメタデータを解釈することにより、Read-Committed分離レベルにおいて有効なデータのみをユーザに見せる 2. WALメタデータを省いてScalarDB上のテーブルと同じスキーマを提供する、という役割を担っています。これらにより、ユーザはWAL-Interpreted ViewをScalarDB上のテーブルと同等のものと考えることができるようになります。

Schema Importerは上記のデータベースオブジェクトを自動的に設定するためのCLIツールです。Schema Impoterは指定されたScalarDBの設定ファイルを読み、ScalarDB上に定義されたテーブルのスキーマを取得して、それらに対応したFDW、外部テーブル、WAL-Interpreted Viewを順に作成します。これにより、ユーザは、ScalarDB上に定義されたテーブルが、あたかもPostgreSQL上にあるかのように操作することが可能になります。

サンプルコード

実際にSchema ImporterによってどのようなWAL-Interpreted Viewが得られるのかを、具体例を用いながら説明します。以下のように、ScalarDB上で`dynamons.customer`, `postgresns.order`, `cassandrans.lineitem`のテーブルが作成されているとします。それぞれのテーブルは、ScalarDBによってDynamoDB、PostgreSQL、Cassandraに保存されています。

この時に、Schema Importerを実行すると、3つのテーブルそれぞれについて、外部テーブルとビューが作成されます。例えば、dynamons.customer テーブルに対して、dynamons._customerという外部テーブルと、dynamons.customerというビューが作成されます。

                            Foreign table "dynamons._customer"
Column | Type | Collation | Nullable | Default | FDW options
------------------------+------------------+-----------+----------+---------+-------------
c_custkey | integer | | | |
c_name | text | | | |
c_address | text | | | |
c_nationkey | integer | | | |
c_phone | text | | | |
c_acctbal | double precision | | | |
c_mktsegment | text | | | |
c_comment | text | | | |
tx_id | text | | | |
tx_version | integer | | | |
tx_state | integer | | | |
tx_prepared_at | bigint | | | |
tx_committed_at | bigint | | | |
before_tx_id | text | | | |
before_tx_version | integer | | | |
before_tx_state | integer | | | |
before_tx_prepared_at | bigint | | | |
before_tx_committed_at | bigint | | | |
before_c_name | text | | | |
before_c_address | text | | | |
before_c_nationkey | integer | | | |
before_c_phone | text | | | |
before_c_acctbal | double precision | | | |
before_c_mktsegment | text | | | |
before_c_comment | text | | | |
Server: multi_storage_dynamodb
FDW options: (namespace 'dynamons', table_name 'customer')
                     View "dynamons.customer"
Column | Type | Collation | Nullable | Default
--------------+------------------+-----------+----------+---------
c_custkey | integer | | |
c_name | text | | |
c_address | text | | |
c_nationkey | integer | | |
c_phone | text | | |
c_acctbal | double precision | | |
c_mktsegment | text | | |
c_comment | text | | |

dynamons.customerビューは、ScalarDB上の元のテーブルと同等のスキーマになっています。ユーザはこのビューに対して、あたかもScalarDB上のテーブルに対して行っているかのように、クエリを実行することが可能です。PostgreSQLでは様々な分析クエリがサポートされているため、例えば、次のようなクエリを実行することが可能です。

> SELECT
l_returnflag,
l_linestatus,
sum(l_quantity) AS sum_qty,
sum(l_extendedprice) AS sum_base_price,
sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
avg(l_quantity) AS avg_qty,
avg(l_extendedprice) AS avg_price,
avg(l_discount) AS avg_disc,
count(*) AS count_order
FROM
cassandrans.lineitem
WHERE
to_date(l_shipdate, 'YYYY-MM-DD') <= date '1998-12-01' - 3
GROUP BY
l_returnflag,
l_linestatus
ORDER BY
l_returnflag,
l_linestatus;

l_returnflag | l_linestatus | sum_qty | sum_base_price | sum_disc_price | sum_charge | avg_qty | avg_price | avg_disc | count_order
--------------+--------------+---------+--------------------+--------------------+--------------------+---------------------+--------------------+---------------------+-------------
A | F | 1519 | 2374824.6560430005 | 1387363.5818635763 | 1962762.9341866106 | 26.6491228070175439 | 41663.590456894744 | 0.4150182982456142 | 57
N | F | 98 | 146371.22954200002 | 85593.92837883368 | 121041.52567369482 | 32.6666666666666667 | 48790.409847333336 | 0.4098473333333333 | 3
N | O | 5374 | 8007373.247144971 | 4685645.630765834 | 6624209.157932242 | 24.4272727272727273 | 36397.15112338623 | 0.414759749999999 | 220
R | F | 1461 | 2190869.967642001 | 1284177.8484816086 | 1814150.7929095028 | 25.1896551724137931 | 37773.62013175864 | 0.41323520689655185 | 58
(4 rows)

まとめ

本記事では、ScalarDB Analytics with PostgreSQLの紹介とその仕組みを紹介しました。より詳細な使い方はドキュメントをご参照下さい。Scalarでは、ScalarDBで管理されたデータの価値をさらに高めていくため、PostgreSQLに限らず、更に多様な環境でのデータ分析を可能にしていく予定です。

--

--

Akihiro Okuno
Scalar Engineering (JA)

Software Engineer, Ph.D., specializing in database engineering.