2025年2月5日

Cloudflare、Unikernels、ベアメタル:Prisma Postgres クエリのライフサイクル

Prisma Postgres は、市場で最も革新的な PostgreSQL データベースです。この記事では、その技術スタックを深く掘り下げ、驚異的な高速クエリ、グローバルキャッシュ、コネクションプーリングなどを実現する仕組みを解説します。

再確認:Prisma Postgres とは?

まだご存知ない方のために:Prisma Postgres は、ユニカーネル上に構築された初のデータベースです。見逃した方は、こちらの100秒の簡単な要約をご覧ください。

次世代インフラストラクチャ上に構築

Prisma Postgres は、単なる AWS ラッパーではありません!そのアーキテクチャは、第一原理から注意深く設計されており、ユニカーネルUnikraft CloudCloudflare Workers などの次世代インフラストラクチャ上に構築されています。

これらのテクノロジーの組み合わせは、独自の利点と強力な機能セットを提供します。

コールドスタートなし、グローバルキャッシュ、コネクションプーリングなど

Prisma Postgres をサーバーレスデータベースとして使用すると、開発者は以下のようなメリットが得られます。

  • ゼロ コールドスタート:遅延なくデータベースに瞬時にアクセスできます。
  • 寛大な無料枠:月あたり 10 万オペレーション、1GiB ストレージ、10 データベース。
  • グローバルキャッシュレイヤー:クエリ応答はエッジで簡単にキャッシュされます。
  • 組み込みコネクションプール:TCP コネクションを気にすることなくアプリケーションをスケールできます。
  • パフォーマンスのヒント:クエリの高速化のための AI 駆動の推奨事項。
  • シンプルな従量課金制:オペレーションとストレージに基づいた予測可能なコスト。

Prisma Postgres を試す

Prisma Postgres クエリのライフサイクル

簡単な概要が終わったところで、Prisma Postgres がこれらの利点を実現するために使用している技術スタックを詳しく見ていきましょう。ネタバレ注意:Prisma Postgres クエリのライフサイクルに関わるすべてのコンポーネントの概要は次のとおりです。

Prisma Postgres components

次のセクションでは、各段階を詳しく見ていき、内部で何が起こっているかを説明します。

ステージ 1:すべては Prisma ORM から始まる

Prisma ORM は、Prisma Postgres クエリの旅が自然に始まる場所です。

Prisma Postgres ではアプリケーションサーバー上でクエリエンジンは不要

過去に Prisma ORM を使用したことがある方は、Rust で実装され、アプリケーションサーバー上でバイナリとして実行されるクエリエンジンを使用していることをご存知かもしれません。

この文脈ではクエリエンジンが Rust で記述されていることについてまだ言及していますが、現在 TypeScript で書き換えられています。詳細はこちらをご覧ください こちら

クエリエンジンの主な責務は次のとおりです。

  • 高レベル ORM クエリ (JS/TS で記述) に基づいて効率的な SQL クエリを生成する
  • データベースコネクションプールを管理する

Prisma Postgres で Prisma ORM を使用する際の優れた点は、アプリケーションサーバー上でクエリエンジンを実行する必要がないことです。代わりに、クエリエンジンなしの超軽量バージョンの Prisma ORM を使用します。SQL クエリの生成と TCP コネクションの管理という重労働は、スタックのさらに下、Prisma Postgres の上に位置するコネクションプールにプッシュダウンされます。

Prisma Postgres インフラストラクチャ上でコネクションプールをホストするこのアプローチには、大きなメリットがあります。アプリケーション開発者をコネクションプールの管理から解放することで、データニーズとクエリに集中できるようになります。また、コネクションプールを何度も再作成すると大きなパフォーマンスオーバーヘッドが発生するサーバーレスやエッジ関数などの短寿命環境では特に役立ちます。

キャッシュ戦略を用いた Prisma ORM クエリの定義

この記事の目的のために、次の Prisma ORM クエリを使用してみましょう。

このクエリは、データベースから公開されたすべての投稿を取得し、さらに Prisma Postgres キャッシュに関連する 2 つのパラメータを指定します。

  • Time-To-Live (ttl):キャッシュされたデータが新鮮と見なされる期間を決定します。TTL 値を設定すると、Prisma Postgres は、データベースにクエリを実行せずに、その期間キャッシュされたデータを提供します。
  • Stale-While-Revalidate (swr):Prisma Postgres がバックグラウンドで新しいデータをフェッチしている間も、古いキャッシュデータを配信できるようにします。SWR 値を設定すると、Prisma Postgres は、TTL を過ぎても、その期間キャッシュされたデータの配信を継続し、同時にデータベースからの新しいデータでキャッシュを更新します。

この例では、データは 30 秒間 (TTL) 新鮮と見なされます。その後、次の 60 秒間 (SWR)、Prisma Postgres のキャッシュは、バックグラウンドで新しいデータをフェッチしながら、古いデータを提供します。

Prisma Postgres は、アプリケーションに近いエッジロケーションからキャッシュされたデータを提供します。アプリを複数のロケーションにデプロイする場合、このグローバルキャッシュはアプリのパフォーマンスを劇的に向上させることができます!

HTTP 経由でのクエリの実行

上記のクエリがアプリケーションで実行されると、次に何が起こるのでしょうか?クエリエンジンがスタックの下にプッシュダウンされたため、この段階で起こることは、Prisma Postgres インフラストラクチャの最初の認証およびルーティングレイヤーへの HTTP リクエストだけです。この HTTP リクエストは、クエリの軽量な JSON ベースの表現を運びます。以下にその様子を示します。

selection 引数は、データベースからフェッチする必要があるフィールドを指定することに注意してください。クエリで select オプションまたは include オプションを使用しなかったため、その値は単に "$scalars": true となり、ターゲットモデルのすべてのスカラーフィールドがデータベースから返されることを意味します。

リクエストの次のステップは、Prisma Postgres の認証およびキャッシュレイヤーによって評価されることです。

ステージ 2:リクエストの認証

クエリ結果をキャッシュから提供できるかどうかを確認するためにキャッシュにヒットする前に、クエリを認証する必要があります。Prisma Postgres URL には、常にユーザー認証情報をエンコードする apiKey 引数が含まれています。

認証レイヤーは Cloudflare Workers を使用して実装されており、そのためクエリの発信元に物理的に近い場所にあります。認証レイヤーは apiKey 値を使用してユーザーを識別し、アクセス許可を検証し、リクエストを次のステージにルーティングします。

ステージ 3:キャッシュするかしないか

認証後、HTTP リクエストは、Prisma Postgres インフラストラクチャの次のレイヤーにヒットします。これも Cloudflare Workers を介して実装されています。

このルーティングレイヤーの主な目的は、Prisma Postgres キャッシュをアクティブ化する必要があるかどうかを判断することです。

  • クエリに swr オプションまたは ttl オプション、あるいはその両方が設定されている場合、クエリは Prisma Postgres キャッシュへのパスに入ります。
  • クエリにこれらのキャッシュオプションのいずれも設定されていない場合、次のステージに直接移動します。

それでは、Prisma Postgres のキャッシュレイヤーを通るパスを調べてみましょう。

Cloudflare Workers の上に構築された Prisma Postgres キャッシュは、公式の Cloudflare Cache API を活用しています。

キャッシュキーとして、クエリ全体 (上記の例の published: true などのクエリパラメータの値を含む) に基づいて計算されたハッシュを使用します。このアプローチは、キャッシュミスの側に偏っており、この正確なクエリがデータベースに送信され、その結果が以前にキャッシュされたという 100% の確信がある場合にのみ、キャッシュからデータを返します。

Prisma Postgres ダッシュボードでキャッシュ動作の統計情報を確認できます。

それでは、以前のクエリが Prisma Postgres スタックをさらに下に進み、キャッシュによって提供されないと仮定しましょう。次に何が起こるのでしょうか?

ステージ 4:コネクションプールへのヒット

クエリ結果がキャッシュされていない場合、以前の HTTP リクエストは次の停止点である Prisma Postgres のコネクションプール (データベースインスタンスに物理的に近い VM にデプロイ) に転送されます。

コネクションプーリングが重要な理由の詳細については、最近の記事「コネクションプーリングでブラックフライデーを救う」をご覧ください。

これが実際にはリクエストが長距離を移動する最初で (そして唯一の) 機会であることに注意してください。これは、リクエストが Cloudflare リージョンの地域境界を離れるためです。

これらの VM は、アプリケーションサーバーから移動されたクエリエンジン (ステージ 1 で説明) をホストします。したがって、この段階では、Prisma Postgres のコネクションプールは、実際にクエリを実行するためのアイドル状態のコネクションを見つけるだけでなく、Prisma Postgres に送信される SQL ステートメントも生成します。これは、データベースへの昔ながらの TCP コネクションを介して行われます。

ステージ 5:ユニカーネルデータベースへの突入

Prisma Postgres は、独自のベアメタルサーバー上で超軽量マイクロ VM として実行されるユニカーネル (「高度に特化したオペレーティングシステム」と考えてください) をベースにしています。

Early Access の発表をチェックして、そのアーキテクチャの詳細、Unikraft とのコラボレーション、および Prisma Postgres のパフォーマンス上の利点を可能にするミリ秒クラウドスタックについて学んでください。

これは、Prisma Postgres インスタンスの驚異的な高速起動時間を実現する Unikraft Cloud のコアコンポーネントの概要です。

そして、これらのコンポーネントは連携して動作します。

  • カスタムコントローラーとプロキシ:クラス最高の、リアクティブな、ミリ秒単位のセマンティクスとスケーラビリティを提供するカスタムプラットフォームコントローラー。ネットワーク処理を高速化するために、Unikraft Cloud はこのコントローラーを、ロードバランシングを担当し、受信リクエストに非常に迅速に対応できるカスタムプロキシと組み合わせます。このプロキシは、Prisma Postgres のコネクションプールへの TCP コネクションが管理されている場所です。
  • Firecracker とユニカーネルに基づく高速仮想マシンモニター (VMM):Unikraft Cloud のユニカーネルは、Prisma Postgres のみを含むリーンイメージを使用します。それだけです。変更されたバージョンの Firecracker VMM と組み合わせることで、これらの Prisma Postgres イメージは驚異的な速さで起動します。
  • スナップショット:Unikraft Cloud は、Prisma Postgres インスタンスをゼロにスケールする前に、メモリのスナップショットを取得します。それらをウェイクアップすると、スナップショットから再開されます。つまり、VM はすでに「ウォーム」であり、すでにアクティブな TCP コネクションも含まれています!

この非常に効率的なスタックのおかげで、データベースインスタンスは実際に使用した場合にのみコストが発生します。これにより、必要なだけ多くの無料 Prisma Postgres インスタンスをスピンアップできる寛大な無料枠を提供できます (通常、複数のデータベースインスタンスを作成する場合は月額固定料金を支払う必要がある他のプロバイダーとは対照的です)。

クエリに戻りましょう。クエリの最初の JSON 表現が効率的な SQL ステートメントに変換された後、クエリは最終的に TCP 経由でデータベースレイヤーに到達します。PostgreSQL インスタンスは、コネクションプールに物理的に近い独自のベアメタルサーバー上の Unikraft のミリ秒クラウドスタックを使用してデプロイされます。

ここでの最初の停止点は、コネクションプールへの TCP コネクションの維持を担当する Unikraft プロキシです。

プロキシは、実際の Prisma Postgres インスタンスの管理を担当する Unikraft コントローラーと通信します。この時点で、2 つの可能な状態があります。

  • または、ターゲットの Prisma Postgres インスタンスがすでに起動して実行されている場合。この場合、プロキシは先に進み、クエリを直接転送し続けます。
  • または、Prisma Postgres インスタンスが現在「一時停止」している場合。この場合、プロキシはターゲットの Prisma Postgres インスタンスの識別、インスタンスの「ウェイクアップ」、および現在のインスタンスステータスをプロキシに通知する責任を負う Unikraft コントローラーに連絡します。

ここでの「一時停止」と「ウェイクアップ」の用語に混乱しないでください。超高速 VM スナップショット (メモリ内で発生) とユニカーネルの軽量性のおかげで、各インスタンスは数ミリ秒 (Prisma Postgres インスタンスがコールドスタートに苦しまない理由の秘密) で再びウェイクアップできます。

Prisma Postgres アーキテクチャの今後の展望は?

現在の技術スタックとその開発者にもたらすメリットについて多くの興奮が見られましたが、ここで立ち止まるつもりはありません!

Prisma Postgres の将来のイテレーションで可能と思われる追加の最適化が数多くあります。最も注目すべきは、コネクションプールを Prisma Postgres インスタンスを実行している同じマシンに移動することです。

Future architecture diagram of Prisma Postgres

TCP コネクションは、コネクションが確立されるたびに実行する必要がある 3 ウェイハンドシェイクのために、スタック全体で最もコストのかかる部分です。この TCP コネクションを、同じマシン上の 2 つのプロセス間で発生する単なるローカルコネクションに削減することで、コネクションプールとデータベースインスタンス間の物理的な距離によって引き起こされるレイテンシは完全に無視できるようになります。

これが、AWS (または別のクラウドプロバイダー) インフラストラクチャに基づいた他のプロバイダーと比較した Prisma Postgres のコアアドバンテージです。クラウドプロバイダーを使用する場合、コネクションプールとデータベースインスタンスが同じホスト上で実行されている保証はありませんが、常にネットワークホップが発生します。

結論

この記事では、Prisma Postgres の内部構造と、その基盤となる次世代技術スタックについて見てきました。

すでに Prisma ORM を使用している場合は、既存のデータベースからデータをインポートして Prisma Postgres を試してみてください。または、ターミナルで次のコマンドを実行して、Prisma Postgres を最初から試してみてください。

次回の投稿をお見逃しなく!

Prisma ニュースレターに登録する