🚀

Go ORM徹底比較:GORM vs Ent vs SQLC vs SQLBoiler

に公開3

📋 この記事について

対象読者: 中級Go開発者、Goでバックエンド開発を始めようと考えている方

記事の概要:
この記事では、Goの主要なORMフレームワークであるGORM、Ent、SQLC、SQLBoilerを比較します。

  • GORM、Ent、SQLC、SQLBoilerの基本的な考え方の理解
  • 各フレームワークの機能とユースケースの比較
  • ベンチマークテストの実施と比較検証
  • プロジェクトに適したGo ORMを選択するための情報

ポイントの先取り
今回の調査・検証結果は、以下のようにまとめられます。
Go ORM比較

検証環境:

  • OS: macOS
  • 言語/フレームワーク: Go 1.22
  • その他: Docker

🎯 背景・課題

適切なORM(Object-Relational Mapper)の選択は、Goプロジェクトにおいて非常に重要な決断となります。適切なORMを選ぶことで、開発者の生産性やアプリケーションのパフォーマンスを大幅に向上が期待できるでしょう。しかし、Goのエコシステムには、それぞれ独自の思想やトレードオフを持つさまざまなORMが存在します。この記事では、主要な4つのGo ORMフレームワーク(GORM、Ent、SQLC、SQLBoiler)を比較します。

🔍 調査・検証内容

ベンチマーク手法

パフォーマンスベンチマークは、MacBook Air(M3、24GB RAM)のローカル環境とDockerコンテナ内でGo 1.22を使用して実施しました。各テストは、インメモリSQLiteデータベースに対して10,000回の連続したCRUD(作成、読み取り、更新、削除)操作を実行することで構成されています。提供されたコードサンプルには、使用されたベンチマークロジックが含まれています。

コードサンプル

実行可能なコードサンプルは、以下のディレクトリにあります:

これらのサンプルコードは、go_orms_researchリポジトリ内に格納されています。各ORMのコーディングテストが含まれています。

GORM:多機能なフレームワーク

GORMは、Goエコシステムで最も人気があり、成熟したORMです [1]。伝統的なオブジェクト指向のアプローチに従い、豊富な機能をすぐに利用できます。コードサンプルは上記のリンクを参照してください。

// 作成
db.Create(&Product{Code: "D42", Price: 100})

// 読み取り
var product Product
db.First(&product, "code = ?", "D42")

// 更新
db.Model(&product).Update("Price", 200)

// 削除
db.Delete(&product, 1)

認知度や採用実績

特定の企業名が公にされることは少ないですが、GORMの人気(GitHubで35k以上のスター)とGoコミュニティでの広範な使用は、プロフェッショナルおよびエンタープライズ環境での幅広い採用を示しています。また一般的に成熟し、信頼性の高い選択肢と見なされています。しかし、パフォーマンスが重要なエンタープライズチームの中には、最大限の制御とパフォーマンスを維持するために、ORMの代わりに生のSQLを好むという一般的な傾向があることも注目に値します。これはGORMに特有の問題ではなく、アーキテクチャの選択に関連する考慮事項です。

Ent:コード生成フレームワーク

EntはFacebookによって開発されたモダンなORMです [2]。コード生成アプローチを採用し、データベースと対話するための型安全で明示的なAPIを提供します。

// 新しいユーザーの作成
u, err := client.User.
    Create().
    SetAge(30).
    SetName("a8m").
    Save(ctx)

エンタープライズでの採用

Entは、Meta(旧Facebook)で大規模で複雑なデータモデルを持つサービスを管理するために作成され、後にオープンソース化されました[2]。その採用は着実に拡大しており、現在はLinux Foundationの一部となっており[3]、プロジェクトの安定性の高さが垣間見えるかもしれません。Ariga、Yaesuなどの企業がEntの使用を公にしています。その強力なバックグラウンドと、型安全でスキーマ駆動の開発に重点を置いていることから、高い信頼性と保守性を必要とするエンタープライズアプリケーションにとって信頼できる選択肢となるかもしれませんね。

SQLC:SQLファーストのフレームワーク

SQLCは伝統的なORMではありません。SQLクエリから型安全なGoコードを生成します [4]。このアプローチにより、型安全なAPIの利点を提供しつつ、SQLの全機能を利用できます。

-- name: GetUser :one
SELECT * FROM users
WHERE id = ?;
user, err := queries.GetUser(ctx, 1)

認知度や採用実績

SQLCはEntのような著名な企業の後ろ盾はありませんが、Goコミュニティ内で強力かつ成長している採用実績があり、Coder、Cerbos、Scalewayのような企業が本番環境で使用しています [5]。エンタープライズの文脈でのその魅力は、開発者が記述したSQLから直接型安全なGoコードを生成することによって提供される安全性とパフォーマンスにあるようです。このアプローチは、ORMのオーバーヘッドを完全に回避し、生のSQLのパフォーマンスと生成されたコードのコンパイル時安全性を両立させたいチームにしばしば好まれるかもです。

SQLBoiler:データベースファーストのフレームワーク

SQLBoilerは、既存のデータベーススキーマからGoコードを生成する「データベースファースト」のアプローチを取ります [6]。このアプローチは、データベーススキーマが信頼できる情報源であるプロジェクトに最適です。

// 新しいユーザーの作成
u := &models.User{Name: "John"}
err := u.Insert(ctx, db, boil.Infer())

// 読み取り
user, err := models.Users(models.UserWhere.ID.EQ(1)).One(ctx, db)

// 更新
user.Name = "Jane"
rowsAff, err := user.Update(ctx, db, boil.Infer())

// 削除
rowsAff, err := user.Delete(ctx, db)

認知度や採用実績

SQLBoilerは、特定の企業による大規模な採用は公表されていませんが、そのパフォーマンスと型安全性から、本番環境での使用にも適していると言えるでしょう。特に、データベーススキーマが明確に定義され、安定しているプロジェクトで好まれる傾向があるかもしれません。開発者コミュニティでは、リフレクションを使用しないことによる速度と、コンパイル時の型チェックによる安全性が高く評価されています[6]。

📊 パフォーマンス比較結果

機能 GORM Ent SQLC SQLBoiler
考え方 多機能 コード生成 SQLファースト データベースファースト
型安全性 ランタイム コンパイル時 コンパイル時 コンパイル時
使いやすさ 簡単 普通 普通 普通
柔軟性 高い 普通 高い 普通
パフォーマンス 良い 非常に良い 非常に良い 非常に良い

ベンチマーク結果

ベンチマーク結果

サンプルコードによるテストでは以下の結果が得られ、SQLC、Ent、SQLBoilerがCRUD操作で優れたパフォーマンスを提供することが確認されました。

Docker環境での結果 (Linux, Go 1.22)

🚀 Go ORM Benchmark Testing
===========================

📊 Running Performance Benchmarks...
Testing GORM...      ✅ 82.6ms
Testing SQLC...      ✅ 15.1ms
Testing Ent...       ✅ 15.6ms
Testing SQLBoiler... ✅ 16.8ms

🏆 BENCHMARK RESULTS
====================
SQLC:      15.1ms
Ent:       15.6ms
SQLBoiler: 16.8ms
GORM:      82.6ms

🥇 Fastest: SQLC (15.1ms)

ローカル環境での結果 (macOS, Go 1.22)

🚀 Go ORM Benchmark Testing
===========================

📊 Running Performance Benchmarks...
Testing GORM...      ✅ 57.5ms
Testing SQLC...      ✅ 10.6ms
Testing Ent...       ✅ 11.7ms
Testing SQLBoiler... ✅ 9.1ms

🏆 BENCHMARK RESULTS
====================
SQLBoiler: 9.1ms
SQLC:      10.6ms
Ent:       11.7ms
GORM:      57.5ms

🥇 Fastest: SQLBoiler (9.1ms)

主な調査結果:

  • GORM は最も簡単に始められますが、型安全性とパフォーマンスが若干犠牲になる可能性
  • Ent は型安全性、パフォーマンス、使いやすさのバランスが取れていますが、コード生成のステップが必要
  • SQLC は最もパフォーマンスが高く柔軟な選択肢ですが、生のSQLクエリを記述する必要
  • SQLBoiler はデータベーススキーマからコードを生成するため、型安全で高性能ですが、スキーマ変更時にコードの再生成が必要

🤔 なぜランキングが変わったのか?

ローカル環境とDocker環境でベンチマーク結果が逆転する現象は、単なる環境差ではなく、**「仮想化によるレイテンシ増幅効果」**と各ライブラリのアーキテクチャの相互作用によって説明できます。

仮想化による「レイテンシ増幅」効果

Docker Desktop for Macは、VirtioFSを利用した軽量Linux仮想マシン上で動作します [9]。VirtioFSは高性能ですが、ネイティブ実行と比較して無視できないI/Oおよびシステムコールのレイテンシオーバーヘッドが依然として存在します [8]。この遅延が「増幅器」として機能し、ライブラリ内部のわずかなCPUオーバーヘッドでさえ、全体の実行時間に大きな影響を与えます。

アーキテクチャと環境の相互作用

  • ネイティブmacOS環境(低レイテンシ):
    この環境はCPUバウンドになりがちです。I/Oが高速なため、ライブラリ自体のCPU効率がパフォーマンスを直接決定します。SQLBoilerの高度に最適化された生成コードと、リフレクションを一切使用しない設計がこの環境で優位に立ちます [6]。

  • Docker on macOS環境(高レイテンシ):
    この環境はI/Oバウンドに変わります。VirtioFSによる一定のI/O待機時間が加わるため、CPUオーバーヘッドが最小のライブラリが最も有利になります。SQLCは、生のSQLから最小限のラッパーコードを生成するため、ランタイムオーバーヘッドがほぼゼロです [4, 7]。この「I/O透過性」が、高いI/O待機時間の上でペナルティを最小限に抑え、最速の結果につながります。一方、SQLBoilerのクエリModシステムがもたらすわずかなオーバーヘッドは、高いI/O待機時間と組み合わさることで、測定可能なペナルティとして現れます。

戦略的示唆:「本番環境に近い」という前提への挑戦

一般的なLinux本番環境(ベアメタルやKVMなど)は、ネイティブmacOSと同様に低いI/Oレイテンシを持つ可能性が高いです。したがって、今回のケースでは、Docker on Macのベンチマークよりも、ネイティブmacOSのベンチマーク(SQLBoilerが最速)の方が、本番Linux環境での相対的なパフォーマンスをより正確に予測している可能性が示唆されます。パフォーマンス評価における環境忠実度の重要性を強調する結果と言えます。

🏆 ベストプラクティスと推奨事項

アーキテクチャの考慮事項: gRPC vs RESTful API

ORMの選択は、APIアーキテクチャによっても影響を受けることがあります [10]:

  • RESTful API: 多くの場合、迅速な開発と柔軟性を重視。GORMは、使いやすさと「多機能」なアプローチにより、迅速な反復と幅広いデータベース互換性が重要なRESTfulサービスに良いかも...
  • gRPC API: 通常、パフォーマンス、強い型付け、スキーマファーストの設計を重視。Ent、SQLC、SQLBoilerは、gRPCの特性とよく合致する可能性。Entのコード生成は型安全性を保証し、Protobuf定義とシームレスに統合。一方、SQLCのSQL-ファーストアプローチとSQLBoilerのデータベースファーストアプローチは、高スループットのgRPCサービスでしばしば重要となる最大限のパフォーマンスと制御を提供。

本番環境での使用:

  • Ent はほとんどのアプリケーションに適している。機能、パフォーマンス、型安全性のバランスがポイント。
  • SQLC は、複雑なSQLクエリを記述する必要があるパフォーマンスが重要なアプリケーションに最適。
  • SQLBoiler は、データベーススキーマが安定しており、最高のパフォーマンスと型安全性が求められる場合に強力な選択肢。

開発での使用:

  • GORM は、迅速なプロトタイピングや小規模なプロジェクトに最適かも。

※ ただ、今の時代はAIによるコード補完で比較的簡単にコードを書いてくれるので、本番と開発環境で同じORMを使用した方がコードやフォーマットに慣れるので、開発しながらコードの質も高めていけるかもしれません。

🎉 まとめ

適切なGo ORMの選択は、特定のニーズと好みに依存します。なので、テストコードを探索してみたり、実際にコードを書いてみましょう!
一般的には、GORMは初心者や小規模プロジェクトに最適です。Entはほとんどのアプリケーションに適した万能な選択肢です。SQLCとSQLBoilerは、パフォーマンスが重要なアプリケーションに最適な選択肢とカテゴリ分けできるでしょう。

主なポイント:

  • GORMは使いやすいが、パフォーマンスは劣る
  • Entはコード生成ステップを持つ、型安全でパフォーマンスの高いORM
  • SQLCは生のSQLを記述する必要がある高性能な選択肢
  • SQLBoilerはデータベーススキーマからコードを生成する、型安全で高性能な選択肢

📚 参考資料

  1. GORM - The fantastic ORM library for Golang
  2. Ent - An entity framework for Go
  3. Ent Joins the Linux Foundation
  4. SQLC - Generate type-safe code from SQL
  5. SQLC - Who's Using SQLC?
  6. SQLBoiler - A tool for generating a Go ORM tailored to your database schema.
  7. SQLc in Golang. Type-Safe SQL Code Generation for… | by Sandeep | Medium
  8. Docker on MacOS is still slow? - Paolo Mainardi
  9. Instantly Improve Docker Performance on Mac - Nimbus
  10. gRPC vs. REST: A Tale of Two API Paradigms

その他参考資料

Discussion

SoraSora

有益な記事ありがとうございます!この3つの順位はイメージしてた通りでした!sql boilerがこの中のどこに入ってくるのか気になりました!もし気が向いたら検証の検討してくださると嬉しいです🙏

RarinoRarino

コメントありがとうございます!
SQL boilerの検証結果を追加しました!
DockerとローカルのmacOS上でテストしたのですが、SQL boilerだけ順位変動があったので、とても興味深かったです🤔

SoraSora

迅速な検証ありがとうございます!まさかのsql boilerが1位😯
勝手にEntの次くらいかなと思ってたので、勉強になりました!
今のプロジェクトでsql boiler使ってるのですが、このまま使い続けようと思います!ご検証いただきありがとうございました!メンテナンスモードになったのがちょっと残念ですが🥲