当社は、Prisma ORM、TypeORM、Drizzle ORM と、AWS RDS の PostgreSQL、Supabase、Neon などの様々なデータベースプロバイダーとの間のクエリレイテンシを比較するために、オープンソースのパフォーマンスベンチマークを作成しました。当社の手法と、どの TypeScript ORM が最速であるかについて、続けてお読みください。

目次
要約
アプリケーションに最適なORMを選択するには、いくつかの要素を考慮する必要がありますが、その中でも「クエリパフォーマンス」は重要な要素です。
TypeScriptアプリでどのORMを使用するかを決定するのに役立つよう、Prisma ORM、TypeORM、Drizzle ORM(そのクエリAPIを使用)の3つのORMライブラリのクエリパフォーマンスを比較するオープンソースのパフォーマンスベンチマークを作成しました。
ベンチマーク結果を見る
では、最速のORMはどれか?(もしかしたら不満に思われるかもしれない)答えは、「状況によります!」
収集したデータに基づくと、あるORMが常に他のORMよりも優れていると結論付けることはできません。むしろ、それは個々のクエリ、データセット、スキーマ、そしてクエリが実行されるインフラストラクチャに依存します。
Prisma ORMクエリの最適なパフォーマンスを確保するために、以下のパフォーマンスチェックリストをご覧ください。
ベンチマーク手法
クエリパフォーマンスを測定し比較することは困難な作業であり、公正な比較を行うためには多くの要素を考慮する必要があります。
今回のベンチマークでは、間接的なレイヤーやデータ処理を多層にすることなく、シンプルで分かりやすく保ちつつ、人々が次のプロジェクトでどのORMを使用するかについて情報に基づいた意思決定ができるよう、ベンチマークが公正で有意義であることを保証するバランスを取ることを目指しました。
クエリパフォーマンスの測定に使用したアプリケーションはこちらから入手できます。
セットアップ
Prisma ORM、TypeORM、Drizzle ORM 用に、それぞれ同等の14個のクエリを作成しました。これらのクエリは、4つのPrismaモデル(裏側で追加のリレーションテーブルを使用する暗黙的なm-n関係により5つのテーブル)を持つスキーマに対して送信されます。
各クエリのレイテンシは、この関数を使用してperformance.now()
で測定されます。
例えば、Prisma ORM のプレーンなfindMany
クエリは次のように測定できます。
各ORM、各データベースごとに1つのスクリプト(例: prisma-postgres.ts
)があり、すべての14個のクエリのレイテンシを個別に測定し、結果を.csv
ファイルに保存します。
スクリプトは、様々なプロバイダーでホストされているPostgreSQLデータベースに対して、EC2インスタンス上で実行されました。
データベース接続は、各スクリプトの開始時に確立され、終了時に閉じられます。
データ準備
サンプルデータはfaker.jsを使用してシードされます。決定論的な方法で同一のサンプルデータセットを再作成するために、faker
インスタンスにseed
値が提供されます。
データセットのサイズは、ベンチマーク実行時に設定可能です。これにより、テーブルごとに作成されるレコード数が決定されます。例えば、サイズ1000
のデータセットが作成された場合、Customer
、Product
、Address
テーブルには1,000レコードが、Order
テーブルには10,000レコードが作成されます(Order
テーブルはProduct
との多対多の関係のため、データセットをより現実的にするために10
倍されています)。
ベンチマーク実行
ベンチマークを実行するには、次のようにスクリプトを呼び出します。
これにより、テーブルあたり1,000レコードのデータセットに対して、定義済みのクエリが500回実行されます。データベースURLは、代わりに環境変数として指定することもできます。
データを収集するために、実際の使用シナリオをシミュレートするため、本番環境のインフラストラクチャでベンチマークを実行しました。スクリプトは、以下のスペックのEC2インスタンスから実行されました。
使用したデータベースのスペックは以下の通りです。
ベンチマーク結果の公開
当社が実行したベンチマーク結果は、https://benchmarks.prisma.io で公開しています。
この表は、クエリレイテンシを測定するために実行した500回のイテレーションの中央値を表示しています。500回のイテレーションから、99パーセンタイル(p99)を超える値を除外することで外れ値を破棄していることに注意してください。
表の列は3つのORMライブラリを表し、行はベンチマークされたクエリを示しています。
セルを展開すると、クエリに関する詳細をいくつか表示できます。
- 結果を生成したクエリの実際のコードスニペット。
- 収集されたデータの分布を視覚化したヒストグラム。これらのチャートでは、より多くのイテレーションでレイテンシが低かったことを示すため、左側のバーが高いほど優れています。
注意点
ベンチマークは本質的に難しいテーマであり、正確に行うのは困難です。企業がパフォーマンスベンチマークを公開する場合、通常は自社製品が市場で最速であることを示しますが、他の人が結果を再現することを困難にし、生データの収集から結果の提示までの経路を不明瞭にすることがあります。
当社は、理解しやすく、有意義な結果を生み出す公平で中立的なセットアップを作成するために最善を尽くしました。そうは言っても、ベンチマーク結果を見る際に考慮すべきいくつかの注意点があります。
- TypeORM と Drizzle ORM は API がより制限されており、一部の Prisma ORM クエリ(ネストされた作成など)は、それらの上位レベルの抽象化では表現できません。これらの場合、私たちはそれらの SQL クエリビルダーを使用するようにしています。
- ネットワークレイテンシにより、イテレーション間で結果に変動が生じることが予想されます。その影響を軽減するために、ベンチマークを500回実行し、公開されたベンチマーク結果では中央値とヒストグラムを使用して結果を示しています。
- さらに、ネットワークレイテンシを最小限に抑えるため、クエリが実行されるマシンがアクセスされるデータベースと同じリージョンに配置されていることを確認しました。
- 今回のベンチマークでは、DBレベルまたはOSレベルのキャッシュの影響を軽減するための対策は行っていません。
- すべてのベンチマークイテレーションは、それぞれのORM/ドライバーライブラリのデフォルトの接続プールサイズを使用しています。
- ベンチマークのセットアップを可能な限り現実的にすることを目指しましたが、スキーマとクエリにおいてはいくつかのトレードオフをしました。例えば、スキーマに特別なインデックスを追加せず、各ORMのより高レベルなAPIを適切に比較できるように、意図的に単純なクエリを使用することもありました。
ベンチマークを自分で簡単に実行できるように、多くの努力を払いましたので、ぜひ試してみてください。改善に貢献したい場合は、お気軽にご連絡ください!
最速のORMはどれか?
不満に思われるかもしれませんが、答えはいつものように「状況によります」です。パフォーマンスは複雑で微妙なテーマであり、様々な要因に依存するため、予測することは非常に困難です。
クエリが最適な速度であることを確認するために、以下のパフォーマンスチェックリストをご覧ください。
その質問に対して決定的な答えを出すことはできませんが、いくつかのパターンを見て分析することはできます。
データベースプロバイダー間の分散の低さ
まず、データベースプロバイダー間の差は、一般的に無視できるほど小さいことがわかりました。例えば、プレーンなfindMany
クエリだけを見ると、中央値とヒストグラム分布から、パフォーマンスの分散が低いことがわかります。
おそらくRDSは、ベンチマークスクリプトが同じセキュリティグループ内のEC2インスタンスから実行されたのに対し、SupabaseとNeonのDBはパブリックインターネット経由でアクセス可能であるため、有利であったと思われます。
詳細については、ベンチマークサイトを訪れて結果を検査するか、ご希望のデータベースプロバイダーを使用してベンチマーク結果をご自身で実行してください。
ほとんどのクエリは同程度のパフォーマンス範囲内にある
全体的に見て結果を遠くから見ると、ほとんどのクエリはわずか数ミリ秒の差で同様の範囲内で実行されていることがわかります。例として、AWS RDSで収集した結果を以下に示します。
UX調査によると、100ms未満の遅延はユーザーには知覚されず、システムは依然として瞬時に感じられるため、ほとんどの場合、これらのわずかな違いは次のプロジェクトでどのORMを使用するかを選択する際の主要な要因となるべきではありません。
もちろん、データベースクエリのレイテンシは、構築しているアプリ全体のパフォーマンスにおける『1つの』要素にすぎません。そのため、他の側面、特にシステムが持つすべてのネットワーク境界(HTTPレイヤーなど)も測定し、最適化するようにしてください。
主な外れ値:ネストされた全件検索
ネストされた全件検索クエリは、すべてのORMとすべてのデータベースプロバイダーにおいて特に低速でした。これは次のようなシンプルなクエリです。
Prisma ORM
Drizzle ORM
TypeORM
RDSを例にとると、収集した結果の中央値は次のとおりです。
このクエリは、2つの異なるテーブルからデータをフェッチし、返されるデータ量が相当なため、他のクエリと比較してすべてのORMで大幅に低速であることが示されました。
結論
収集したデータは、各ORMの個々のパフォーマンスについて決定的な結論を出すことを許しません。クエリパフォーマンスに関する厳しい真実は、各ORMライブラリで高速なクエリも低速なクエリも書くことが可能であるということです。
結局のところ、アプリケーションのパフォーマンスの多くは、開発者がベストプラクティスに従い(以下のパフォーマンスチェックリストを参照)、遅いクエリを特定し、時間をかけてそれらを最適化する能力に依存します。
Prisma ORMクエリのパフォーマンスを向上させる
パフォーマンスはPrismaにとって極めて重要な役割を果たしており、当社は最近、この分野でPrisma ORMの様々な側面を改善することに力を入れてきました。例えば、DBレベルのJOINを使用するオプションの導入、v5
での多くのパフォーマンス改善の実装、サーバーレスのコールドスタートを9倍高速化、または最新の5.17.0
リリースで$queryRaw
の速度を2倍向上させました。
Prisma ORMのパフォーマンスチェックリスト
Prisma ORMクエリが最適なパフォーマンスであることを確認するのに役立つ基本的なチェックリストです。
- サーバーとデータベースを同じリージョンにホストする。
- クエリで頻繁に使用される列にインデックスを追加する。
- 本番環境では、最低3つのCPUコアが利用可能であることを確認する。
- 必要に応じて、パフォーマンスを測定し、生のSQLでクエリを最適化する。
- Prisma ORM のOpenTelemetryトレーシング機能とメトリクス機能を使用してクエリを監視する。
- データベースにキャッシングレイヤーを追加する(例:Prisma Accelerate)。
- アプリがサーバーレスの場合、サーバーレスパフォーマンスのベストプラクティスに従う。
これらの推奨事項に従ってもまだクエリが遅い場合は、GitHubでクエリの詳細を記載してイシューを開いてください。これにより、クエリが本来の速度で動作していることを確認できます!
Prisma Optimizeによる洞察と推奨事項
パフォーマンス測定とPrisma ORMクエリの高速化をサポートするために、当社は最近Prisma Optimizeをリリースしました。
Optimizeは、Prisma ORMを介してデータベースに送信されるすべてのクエリをキャプチャし、詳細なトレース情報とともにそれらのパフォーマンスに関する洞察を提供します。将来的には、Optimizeは、例えば「返される行数が過剰な場合」や「スキーマのどこにインデックスを定義すべきか」を推奨するなど、遅いクエリを高速化するための推奨事項を提供できるようになります。
ベンチマーク結果を確認する
当社のベンチマーク実行結果は、https://benchmarks.prisma.io でご覧いただけます。ぜひご覧になり、X や Discord でご意見をお聞かせください。このベンチマークを皆様にとってさらに役立つものにする方法について、特に皆様のご意見を伺いたいと思っており、改善のご提案も歓迎いたします!
次の投稿をお見逃しなく!
Prismaニュースレターに登録する