📐

高速データ変換とトランザクション処理を両立するためのデータベース設計

まえがき

フォルシアでは長年検索に特化したアプリケーションを開発してきましたが、近年注力しているプラットフォームのwebコネクトにおいては検索領域に留まらず商品販売に求められるあらゆる機能を提供しています。

webコネクトにおいて、ほぼ全ての商材データを管理する領域が素材登録システム(造成領域)です。素材登録システムでは商品販売に必要な情報の登録、管理に加え、サイトコントローラーなどの外部システムとの商品連携や、検索領域、予約領域を始めとした外部システムへのデータ配信を担っています。

そんなwebコネクトにおける「データの肝」である素材登録システムには、これまで我々が提供してきた検索領域とは全く異なるシステム設計が求められます。特に、フォルシアの高速検索に寄与している技術や開発ノウハウの多くは素材登録システムの要求と噛み合わないため、既存資産の有効活用が難しいという点が設計開発の大きな壁となっていました。
造成領域は検索領域と比べ社内ノウハウも多くなく、フォルシアにとってチャレンジングな開発でしたが、最終的には既存の資産を有効活用しつつ、システムの要求に十分応える仕組みに行き着くことができました。

本稿では、フォルシアがこれまで開発してきた検索領域と比較しつつ、素材登録システムが採用したフォルシアならではのデータベース設計について紹介します。

検索領域の一般的なアーキテクチャの紹介

はじめに、フォルシアが従前より提供してきた検索領域における一般的なアーキテクチャについて整理します。

検索領域のシステム設計においては、いくつかの重要な制約事項があります。

  • データが外生的
    検索領域はあくまでデータを「検索」させることに特化した領域のため、そのデータソースは検索領域にありません。検索領域が保持している全てのデータは外部データ、あるいは外部データから導出されたものであり、必要に応じて改変および破棄される前提のものとなります。
  • 原則としてデータの即時更新が不要
    緊急停止や料金、在庫の更新など実際の販売に関わる要素を除けば、情報更新は即時性が要求されません。勿論リアルタイムに近いならそれが望ましいですが、一般的にはユーザーが選択内容を確認する段階でリアルタイムの情報が連携されていれば良く、検索時の掲載情報はキャッシングが許容されます。
  • エンドユーザーは参照のみを行う
    エンドユーザーのできる操作は「条件を指定して商品を選ぶこと」に限定されます。商品の購入に伴い在庫の変動が起きますが、これはあくまで予約操作によって造成領域の情報が更新されたことによるもので、エンドユーザーが直接検索領域の保持しているデータを更新した結果ではありません。

これらの制約のもとでは、工夫次第で一般的なwebサービスのデータベースに求められるACID特性を度外視した設計が可能となります。実際に検索領域のデータベースでは、OLTP性能を犠牲にOLAP性能に特化させるような拡張やチューニングを数多く施しています。

結果として、検索領域におけるデータベース設計はどちらかというとデータ分析基盤に近いような構成をとります。
検索領域のデータベースでは主に「データの変換、圧縮」と「オンラインでの複雑な検索」を行います。
フォルシアでは一般的に前者を担う層をバッチ層、後者をアプリ層と呼称しています。

バッチ層はいわばETLであり、独自の拡張や技術を用いて顧客データを高速に圧縮し独自のデータ形式へと変換します。バッチ層のデータは配布用のDBが構築でき次第破棄してよく、揮発性を前提とした設計になっています。

アプリ層はいわばDWHであり、こちらも独自の拡張や技術を用いて高速検索を実現しています。データの更新が一方向であり厳密なトランザクションが要求されないため、スケールアウトが容易に行えます。

フォルシアではバッチ層、アプリ層ともにRDBであるPostgreSQLを使用してきました。一般的に利用されているETLやDWHツール、あるいはNoSQLなどを用いない理由としては以下が挙げられます。

  • 複雑な問い合わせを高速に処理する上で、RDBのフォーマットは非常に柔軟かつ強力なため
  • PostgreSQLは高い拡張性を備えており、適切な設計・チューニングにより非常に高いコストパフォーマンスを発揮するため
  • バッチ層、アプリ層を一気通貫で開発でき、高速性における必須機能である独自拡張がどちらの層においても重要な役割を担うため

素材登録システムの特徴

次に素材登録システムについて整理します。

素材登録システムの概要
素材登録システムの概要

素材登録システムは検索領域とは異なり、不特定のユーザーがアプリケーション経由で直接CRUD操作を行います。このため検索領域と比べると一般的に想起されるwebシステムに近い構成が考えられます。

特徴的なのは、データのやり取りがアプリケーションとは別の層でも発生する点です[1]。エンドユーザーとは別に、商材流入元からデータを取得する処理、出力先にデータを配信する処理が求められます。
流入元、出力先いずれも環境によって利用状況が異なり、また将来的に増減する可能性があります。

今回のシステム構築にあたり、データベース設計において考慮するべき点として以下が考えられました。

  • データの永続層(ストック)はなるべくソリッドであるべき
    検索領域とは異なりデータベースはACID特性を満たすことが求められ、また更新性能も無視できません。このため従来の検索領域で用いていた揮発性を前提とした高速処理や、OLTPを犠牲にした高い検索性能との共存ができません。
  • データの入出力層(フロー)は柔軟かつ高速な設計、開発が可能な既存の資産を活用したい
    メインのDBとは異なり、入出力ともに反映までの遅延が許容されるものが多いです。またインプットが外生的であること、最終的なアウトプットの整合性さえ担保されていれば中間層の整合性は求められないことなどから、検索領域のバッチ層に近い考え方が適用できます。
  • 環境によって扱う領域やデータ規模が異なる
    素材登録システムはかなり大規模なシステムですが、扱っている領域のごく一部を提供することも可能です。提供パターンによって大きく性能要件が異なるため、ミニマムな提供が可能、かつある程度スケールもできる構成が望ましいです。

schemaベースのデータベース設計

ここでは前項までの内容を踏まえ、素材登録システムにおけるデータベース設計がどのようなものになったかを紹介します。

端的に言うと 「1環境1DB、1サービス1schema」 という発想をベースとしています。

設計の解説に移る前に、schemaという概念を説明する必要があります。
PostgreSQLはdatabase(DB)-schema-tableという階層構造をとります。schemaという概念は各RDB製品に存在しますが、その扱いは製品によって異なります。PostgreSQLにおいては名前空間であり、これにより最も柔軟な運用が可能です。PostgreSQLでは1DBに複数schemaの存在が許容されますし、1ユーザーが複数schemaを所有できます。
参考: https://www.postgresql.jp/document/16/html/ddl-schemas.html

素材登録システムでは、提供機能(管理機能、取り込み機能A、配信機能X、…)ごとにschemaを用意し、schemaごとに必要な機能を実装するという形で開発をしています。
schema内でデータに対してどのようなルールを設けるか(無論プロジェクトとしてのルールはありますが)はschemaごとに異なります。
例えばアプリケーションとやり取りするストックサービスはマイグレーションツール以外でのDDLを許容しませんが、データ取り込みを行うフローサービスでは一時テーブルの生成を許容するなどし、高速なデータ変換を実現しています。データ型や関数などもschema単位で管理できるため、意図しない競合を起こすことなくschemaが各々の実装に集中できます。

1環境1DB、1サービス1schemaのDBイメージ
1環境1DB、1サービス1schemaのDBイメージ

DB単位で環境を、schema単位でサービスを提供することで、以下のようなメリットが得られます。

サービス間のデータ連携が省力化できる

schemaはあくまで名前空間なので、全てのサービスは同一のDBを共有します。そのため異なるサービスのデータ参照や更新を1つのSQLで表現できます。
サービスごとのDB分離を必須とした場合はFDW[2]などDB間連携用の追加実装も必須となり、複雑性や実装量がグッと増します。特にデータ取り込みにおいては更新対象の状態によって分岐が発生し、FDW経由での参照がボトルネックとなるケースも考えられるため、同一DB内で処理が完結することは開発面、パフォーマンス面いずれの観点でもよい選択といえます。

提供機能の切り替えや開発時のスコープ把握が容易になる

上でも触れましたが、素材登録は一部領域に絞った機能提供も可能としています。このとき同一のDB上で開発をしていると、意図せず機能間に依存関係を生んでしまい一部のみの提供が困難な設計になることが往々にしてあります。
しかし、素材登録システムの開発において提供機能のスコープはschemaに閉じているため、開発者は自ずと依存関係を意識しながら実装することになります。これは機能のスコープを適切に管理しつつ開発速度を保つ上での大きなサポートになっていると感じます。

インスタンスあたりのデプロイに裁量があり、将来的にはスケールも可能

素材登録システムは商用環境においてAmazon Auroraを採用していますが、(非機能試験を行わない)検証環境などで占有すると最小のインスタンスクラスでもかなり余裕があります。このため、データ量の少ない検証環境では各提供先のDBを1クラスターにまとめ、単一のインスタンスにデプロイしています。
一方で負荷試験環境や本番環境においては提供先単位でインスタンスを用意することになります。今のところはその運用で間に合っていますが、今後より高い負荷が予想される場合はインスタンスの増強、分割といった工夫が必要となります。
ここでもschema単位での実装が活きてきます。特に負荷の大きい機能があった場合、それをschema単位で異なるインスタンスに分離させることで負荷分散が見込めます[3]
取り込み系のサービスは常駐させる必要がないため、実行時のみインスタンスを起動させるといった運用も可能です。また配信系のフローサービスではストックサービスのviewとして実装されているものも多く、これらはより簡易に、リードレプリカを追加するだけでスケールできます。

スケーリングのイメージ
利用状況に応じて異なる単位でデプロイされたインスタンスのイメージ

まとめ

素材登録システムでは環境をDB単位、機能をschema単位で構築するという思想に基づいたデータベース設計を採用しました。これにより、データ永続層ではトランザクション性能を担保しつつ、データ入出力層では既存資産の高速なデータ変換技術を採用することができ、また負荷状況に応じた拡張性を持たせることもできました。
今回紹介した設計はDBレイヤで直接データのやり取りが発生するという素材登録システムの特徴に合わせたものであり、あらゆるデータベースに応用可能という性格のものではありません。しかし、PostgreSQLの仕組みを活用したフォルシアの新しいデータベース設計として、今後のプロダクト開発においても応用の可能性があるものと感じています。

この記事を書いた人

吉田 侑弥
2020年新卒入社
フォルシアにはアクアリビング部という部活がありますが、それにあやかって先日Unityで水槽を作るバーチャルアクアリビング部を始めました。部員は私一人で、完成したため先日廃部となりました。

脚注
  1. 外部連携処理もアプリケーションを経由する設計は可能ですが、フォルシアはDB開発に長けたエンジニアが多いことから、直接のDB処理で完結する設計をとりました。 ↩︎

  2. Foreign Data Wrapperの略で、PostgreSQLのみならず外部のデータやファイルをテーブルのように扱える機能です。外部のPostgreSQLを参照する場合は一般的に postgres_fdw というFDWを使用します。 ↩︎

  3. もちろんインスタンスが分かれる場合は、別途FDWなどDB間連携用の追加機能を用意する必要が生じます。 ↩︎

FORCIA Tech Blog

Discussion