Kyselyのパフォーマンスを検証してみた
Node.js向けの主要ORMである Prisma、Drizzle、TypeORM のパフォーマンスを比較する、Prismaが公開しているベンチマークプロジェクトに、新たに Kysely を追加しました。これにより、既存のベンチマーク結果と合わせて、Kyselyの性能や特徴を他のORMと比較できます。
本記事では、Kyselyを中心に、既存ORMとの速度や効率の違いを具体的なベンチマーク結果をもとに紹介し、プロジェクトに最適なORM選びの参考としていただける内容となっています。
Kyselyとは
Kysely は、Node.js 向けの薄め(軽量)な ORM で、SQL クエリの柔軟性と自由度の高さを重視して設計されています。
従来のフル機能型ORMと比べて、型安全性を保ちつつも複雑なSQLを直接書くことができるため、自由度の高いデータベース操作が可能です。
ベンチマークの取得方法
本記事のベンチマークは、Prismaが公式に公開しているGitHubリポジトリをもとに作成しています。
実際にベンチマークの取得に使ったリポジトリ:
公式リポジトリはこちら:
公式のベンチマーク結果はこちらで確認できます:
公式リポジトリからの変更点
- Kysely用のクエリを追加
- PostgreSQLをDockerで立て、ローカル環境で検証することでネットワークの影響を排除
- 実行順序による結果の違いをなくすため、順番を変えながら実行
信頼性のための配慮
- ローカルPCの他のプロセスを可能な限り停止
- Wi-Fiをオフに設定
- ベンチマーク実行時は他の作業を行わない
結果
実際のデータについては
のresultsディレクトリに含まれています。
主な指標についての集計結果を示します。(太字は一番性能が良い)
中央値
| Operation | Kysely ✅ | Prisma | Drizzle | TypeORM |
|---|---|---|---|---|
| Find all | 16.05ms | 16.85ms | 20.42ms | 6.28ms |
| Filter, paginate & sort | 1.66ms | 2.45ms | 2.29ms | 1.70ms |
| Nested find all | 1054.30ms | 57.43ms | 971.43ms | 99.57ms |
| Find first | 1.03ms | 2.07ms | 2.24ms | 1.61ms |
| Nested find first | 2.20ms | 3.77ms | 3.27ms | 3.58ms |
| Find unique | 0.87ms | 1.61ms | 1.72ms | 0.88ms |
| Nested find unique | 2.03ms | 3.58ms | 3.20ms | 3.09ms |
| Create | 6.30ms | 4.69ms | 7.11ms | 5.70ms |
| Nested create | 6.06ms | 9.60ms | 8.19ms | 7.07ms |
| Update | 2.11ms | 3.07ms | 2.76ms | 2.41ms |
| Nested update | 4.17ms | 7.28ms | 5.53ms | 4.37ms |
| Upsert | 1.96ms | 6.13ms | 2.69ms | 4.55ms |
| Nested upsert | 4.11ms | 8.17ms | 5.53ms | 5.74ms |
| Delete | 3.67ms | 4.50ms | 4.34ms | 3.71ms |
このベンチマークにおける 中央値(Median) は、同じ操作を複数回実行した際の 典型的な実行時間の中心値 を示します。
四分位範囲
| Operation | Kysely ✅ | Prisma | Drizzle | TypeORM |
|---|---|---|---|---|
| Find all | 1.09ms | 1.19ms | 2.55ms | 0.66ms |
| Filter, paginate & sort | 0.40ms | 0.37ms | 0.34ms | 0.31ms |
| Nested find all | 36.98ms | 5.16ms | 35.13ms | 7.65ms |
| Find first | 0.22ms | 0.49ms | 0.77ms | 0.61ms |
| Nested find first | 0.24ms | 0.75ms | 0.60ms | 1.01ms |
| Find unique | 0.15ms | 0.44ms | 0.39ms | 0.24ms |
| Nested find unique | 0.27ms | 0.83ms | 0.72ms | 0.86ms |
| Create | 2.84ms | 2.65ms | 2.82ms | 1.80ms |
| Nested create | 0.86ms | 2.18ms | 1.58ms | 10.30ms |
| Update | 0.31ms | 0.55ms | 0.40ms | 0.60ms |
| Nested update | 0.57ms | 0.82ms | 0.76ms | 0.58ms |
| Upsert | 0.25ms | 0.65ms | 0.33ms | 0.58ms |
| Nested upsert | 0.55ms | 0.83ms | 0.75ms | 0.75ms |
| Delete | 0.44ms | 0.52ms | 0.51ms | 0.39ms |
このベンチマークにおける IQR(四分位範囲) は、同じ操作を複数回実行した際の 典型的な実行時間のばらつき を示します。
- IQR が小さい:中央値付近に結果が集まり、実行時間が安定している
- IQR が大きい:中央値から離れた結果が多く、実行時間にばらつきがある
中央値だけでは分からない安定性を評価する指標として有用です。
標準偏差
| Operation | Kysely ✅ | Prisma | Drizzle | TypeORM |
|---|---|---|---|---|
| Find all | 3.09ms | 4.76ms | 3.91ms | 2.24ms |
| Filter, paginate & sort | 0.87ms | 1.34ms | 1.20ms | 0.99ms |
| Nested find all | 92.04ms | 15.79ms | 94.58ms | 23.34ms |
| Find first | 0.32ms | 0.89ms | 2.62ms | 1.88ms |
| Nested find first | 0.42ms | 1.14ms | 1.42ms | 1.34ms |
| Find unique | 0.17ms | 0.53ms | 0.71ms | 0.58ms |
| Nested find unique | 0.90ms | 1.36ms | 1.62ms | 1.46ms |
| Create | 4.45ms | 10.10ms | 7.85ms | 7.10ms |
| Nested create | 11.55ms | 15.19ms | 11.33ms | 11.86ms |
| Update | 3.55ms | 5.43ms | 4.49ms | 0.95ms |
| Nested update | 1.69ms | 1.79ms | 3.89ms | 1.08ms |
| Upsert | 3.57ms | 2.37ms | 0.59ms | 1.20ms |
| Nested upsert | 3.25ms | 2.99ms | 1.48ms | 1.40ms |
| Delete | 1.11ms | 1.00ms | 3.88ms | 1.36ms |
このベンチマークにおける 標準偏差(StdDev) は、同じ操作を複数回実行した際の 結果のばらつきの大きさ を示します。
- StdDev が小さい:実行時間が中央値付近に集まり、安定している
- StdDev が大きい:実行時間にばらつきが大きく、不安定
IQR と同様に、単純な平均値だけでは見えない安定性を評価する指標として有用です。
考察
中央値(Median)に関する考察
1.ほとんどの操作でKyselyが最速
今回のベンチマークでは、ほとんどの操作において Kysely が最も小さい中央値を示しており、典型的なケースでは最速の実行性能を持つ ことが確認できた。これは、Kysely がクエリ生成および実行において余分な抽象化やランタイム処理を最小限に抑え、SQL に近い形で処理を行っている設計思想が、実行時間の短縮に寄与しているためと考えられる。
2.自由度が高いため書くクエリに大きな影響を受ける
Nested Find Allでは4つの中で最も遅いという結果となった。そのときのKyselyのコードを示す。
jsonArrayFromを使ったことにより遅くなったと考えられる。しかしこれはjsonArrayFromを使わないで書くことによって改善が期待できる。そのため追加で2つのパターンを検証した。
- 2つのクエリで取得(findMany-1-level-nesting-two-queries)
結果
中央値: 58.35ms
元のクエリとの差: -995.95ms (改善率 94:46%)
- Joinして1つのクエリで取得(findMany-1-level-nesting-join)
結果
中央値:77.16ms
元のクエリとの差: -977.14ms (改善率 92.7 %)
このように書くクエリによって大幅にパフォーマンスが異なることがわかる。また2つのクエリを書くケースでは、一番速かったPrismaと差が1ms以内で2番目に早い結果となった。
IQR(四分位範囲)および標準偏差(StdDev)に関する考察
IQR と標準偏差は、同じ操作を複数回実行した際の結果の ばらつきや安定性 を示す指標である。中央値ほど直接的に速度の優劣を示すものではないが、実運用における信頼性や再現性を評価する上で重要である。
今回のベンチマークでは、Kysely は IQR や StdDev においても比較的良好な値を示し、多くの操作で安定した実行性能を発揮している ことが確認できた。
結論
今回のベンチマークから、Kysely はパフォーマンス面で非常に優れた実行性能を示す ことが確認できた。ほとんどの操作で中央値が最小値を示し、IQR や標準偏差も比較的良好で、安定した実行性能を発揮している。
一方で、Kysely は自由度が高いため、書き方によっては遅いクエリを生成してしまうリスク があることも分かった。特に Nested 操作や JSON 関連の関数を使用する場合は注意が必要である。
また、Prisma や他の ORM と比べると、より SQL に近いコードを書く必要がある ため、開発速度や学習コストがやや下がる可能性がある。
そのため、パフォーマンス重視のプロジェクトや柔軟なクエリが必要な場合には有力な選択肢 となる一方で、開発効率やコードの簡潔さを優先する場合にはトレードオフを意識する必要がある。