GraphQLとRDBMSの考察

はじめに


webシステムでデータの相互通信形式はREST APIやgRPCの他にGraphQLによる形式がある。

厳密にはGraphQLの通信形式はAPIとしての機構だが、クエリによってフロントエンド側が柔軟にデータを取得できる。

僕はREST API形式もGraphQL形式も扱ってきているが、GraphQLの優れている点として

  • 各ページにおいてデータをまとめて取得することで、RESTのように何度も通信する必要がない(ケーニヒスベルクの橋の問題)


  • ApolloやurqlなどのGraphQLクライアントとTypeScriptの型定義の組み合わせで強力なスキーマ駆動開発が可能


などが挙げられる。

自分も開発していて数多くの利点を感じている。

一方で僕の中ではGraphQL側が要求する技術的要件の難易度は高いとも思っている。

その理由を次に挙げる。


N+1問題と解決について


GraphQLとRDBMSは残念ながら相性の良い技術の組み合わせとは言えない。

データの捉え方に両者には隔たりがあるからだ。

GraphQLは木構造を辿りながら、データを捉えることで、データ取得の解決方法を提示している。

一方でデータベース(ここではRDBMSとする)ではテーブルを関連づけてデータを取得する解決方法を提示している。

この木構造を辿るという行為は、例えばユーザー一覧の中で投稿一覧を探索する際にそれぞれのリソースをユーザーのデータ分だけ探索してしまうことに繋がる。

これはデータ数が多くなればRDBMSの発行するSQLクエリの数が多くなってしまい、パフォーマンス面で非常に厄介な問題を引き起こす。

RDBMSに詳しいエンジニアの場合、これをテーブル結合で解決しようとするがGraphQLの「必要なデータのみクライアントが指定する」という考え方に背くことになる。

これは 先達者の記事 にもある通りである。

最もリーズナブルな解決方法としては記事にあるとおり、ORM層に自己解決させるというやり方だろう。(ID群を取得し、それをWHERE IN句でまとめて取得するやり方)


木構造と関係性データベース構造の難しさ


GraphQLとRDBMSではデータに対する捉え方が異なる。

この両者が一同に接する接合点でデータをどの粒度で捉えるか、は問題になる。

テーブルの粒度 = GraphQLのスキーマ単位

という考え方は厳密には適用できない、と個人的には考えている。

というより無理に押し込もうとすればするほど上手くいかない。

今のところ共通解は持ち合わせていないが僕の中ではまずGraphQLとして大きなグラフ構造を考えて粒度を決める、その次に必要なテーブルを作成する、というのが良いような気がする。


プロジェクトでGraphQLとREST APIどちらを使うべきか


まずプロジェクトが新規プロジェクトでデータ取得がある程度複雑になるプロジェクトであればGraphQLを採用するメリットはある。逆にいうとそれ以外のケースではお勧めしない。

例えば

  • 既存プロジェクトのリライトやリファクタリング


  • RDBMSの設計が初期段階で歪な構造になっている


こういう状況でGraphQLを採用すれば余計に問題を複雑にするだけである。

実体より手段を先行させないことが大事だと考える。

Back To Top