3 ポイント 投稿者 vtrapplepie 2 시간 전 | まだコメントはありません。 | WhatsAppで共有

Rustでバックエンドをまともに作ったことがある人なら、一度はこの壁にぶつかったことがあるはずだ。データベースが必要になった瞬間、4つのライブラリがそれぞれの思想とトレードオフ、そしてRedditの支持者集団を背負って、こちらをじっと見つめてくる。

私もそうだった。この1年で、Diesel、SQLx、SeaORM、Rusqliteを実際の本番環境にデプロイしてきた。選択がうまくはまったものもあれば、やり直すなら別のものを選ぶケースもある。いくつかは本当に意外だった。

マーケティング的な言説も、「ケースバイケースです」といったごまかしもない。4つすべてを実運用コードで使った人間として、率直な感想を話したい。


2026年、なぜRustでDBを扱うのか?

まずはここを片づけよう。なぜPythonでSQLAlchemyを使わないのか、あるいはNodeでPrismaを使わないのか?

DB中心のアプリケーションでRustを選ばせる理由は3つある。

コンパイル時安全性は、ここでは別次元だ。 これらのライブラリの一部は、文字どおりSQLクエリをDBスキーマと照合してコンパイル時に検証する。カラム名をタイプミスした? コンパイラが捕まえる。WHERE句の型が合わない? コードを実行する前に弾かれる。深夜3時のデバッグがどれだけ減ったか、いくら強調しても足りない。

非同期がついに成熟した。 数年前まで、Rustの非同期DBアクセスは荒削りだった。借用チェッカと格闘し、ライフタイムをジャグリングし、完成度の低いライブラリを相手にしなければならなかった。2026年の今は? 普通に動く。Tokioは堅牢で、ライブラリ側も進むべき道を見つけた。

性能を心配しなくていい。 ORMのオーバーヘッドがリクエスト予算を食いつぶさない。ガベージコレクタがトランザクションの途中で止まらない。クエリが実行され、結果が返り、メモリは決定的に解放される。退屈なくらい安定して動く。


4人の候補

2026年2月時点の最新版とともに見ていこう。

  • Diesel (v2.3.6, 2026年1月) — コンパイル時SQLを備えたフルORM
  • SQLx (v0.8.6, 現在の安定版) — 非同期SQLツールキット(ORMではない)
  • SeaORM (v2.0, 2026年1月) — 非同期優先の動的ORM
  • Rusqlite (v0.38.0, 2025年12月) — 軽量なSQLiteラッパー

これらは、関連する問題を解くための、根本的に異なる道具だ。順に説明していく。


Diesel: あなたより先にバグを見つけるやつ

最も向いているケース: コンパイル時安全性を最大限に重視したい、かつスキーマが安定しているチーム

Dieselは2015年から存在している。Rustの世界では、これはほとんど古代に近い。そしてその成熟度は、最良の意味で表れている。

要点はこうだ。Dieselのコードがコンパイルできたなら、そのSQLは有効である。これはマーケティング文句ではなく、文字どおりそういう仕組みだ。DieselはDBスキーマからRustの型を生成し、コンパイラがあなたの書くすべてのクエリをその型と照合して検証する。

Dieselが今でも強く惹きつける理由

コンパイル時検証は中毒性がある。「コンパイラがテストを回す前に壊れたJOINを見つけてくれた」という体験を一度すると、文字列ベースのSQLに戻るのは無謀に感じる。先月スキーマをリファクタリングして、3つのカラム名を変更し、型も変えたのだが、Dieselは修正が必要なすべてのクエリをコンパイル時に漏れなく示してくれた。本当に、一つ残らず。

ゼロコスト抽象化はスローガンではない。Dieselが生成するSQLは、本質的に手書きのSQLと同じだ。実行計画を比較してみたが、同一だった。ORMの安全性とraw SQLの性能を同時に手に入れられる。

マイグレーションもちゃんとしている。低い基準に聞こえるかもしれないが、他のエコシステムのマイグレーションツールと戦った後だと、Dieselのマイグレーションシステムは驚くほど堅牢に感じる。作成、実行、ロールバック――普通に動く。

率直な欠点

非同期は後付けであって、もともと組み込まれていたわけではない。Diesel自体は同期的だ。非同期を使うにはdiesel-asyncが必要で、これはよく動くが、依存関係が1つ増え、認知負荷も少し増す。SQLxやSeaORMのネイティブ非同期から来ると、この違いは目につく。

学習曲線は急だ。Dieselの型システムは強力で、強力なものは複雑だ。クエリを書き損ねると、コンパイラエラーは技術的には正確でも、40行にわたるジェネリック型の吐瀉物になることがある。読み方はそのうち覚えるが、最初の1週間は厳しい。

動的クエリはつらい。ランタイムに構造が変わるクエリ、たとえばオプションのフィルタを持つ検索エンドポイントのようなものを作ろうとすると、Dieselは抵抗してくる。静的なクエリ形状を好むのだ。クエリが動的になると、ビジネスロジックより型システムと格闘する時間のほうが長くなる。

Dieselを選ぶタイミング

  • PostgreSQLまたはMySQLのプロジェクトで、スキーマが毎週変わるわけではない
  • コンパイル時安全性が絶対に妥協できない
  • 本番で何年も生き続けるコードで、正確性が重要だ
  • 他に特別な理由がないなら第一候補

SQLx: SQLを書けば、安全性もついてくる

最も向いているケース: SQLファーストの開発者で、DSLを学ばずにコンパイル時検証を得たい場合

正直に言おう。SQLxはORMではない。クエリを生成してくれないし、リレーションも管理しない。SQLツールキットだ。だが多くの人がORMの代わりに使う位置で使っているし、率直に言って、多くのプロジェクトではそのほうが良い選択だ。

魔法はこう動く。raw SQLクエリを文字列として書く。SQLxはコンパイル時に実際のDBへ接続し、そのクエリを検証する。テーブルが存在しない、カラム名が違う、型が合わない――そうなればコンパイルエラーだ。Diesel級の安全性を得ながら、普通のSQLが書ける。

SQLxが本当に優れている点

SQLを知っていれば、SQLxはすぐ分かる。学ぶべきクエリDSLはない。新しいメンタルモデルもいらない。すでに知っているSQLを書いて、少しマクロを振りかければ、あとはコンパイラが面倒を見てくれる。SQLxのプロジェクトにジュニア開発者を入れた経験から言っても、かかるのは数時間だ。数日ではない。

初日から非同期。SQLxは非同期Rustのために作られている。Tokioでもasync-stdでも、好きなランタイムを選べばいい。別のクレートも互換レイヤーも不要だ。非同期DBアクセスは本来こうあるべきだ。

QueryBuilderが動的クエリを処理する。ここはSQLxが静かにDieselに勝っている部分だ。ユーザーが12個のフィールドの任意の組み合わせでフィルタできる検索エンドポイントが必要だろうか? SQLxのQueryBuilderなら、そうした動的クエリを直感的に組み立てられる。クエリを断片的に構築しても、依然としてパラメータ化されており、インジェクションに強い。

率直な欠点

コンパイル中にDBが起動している必要がある。これがSQLxについて最も議論を呼ぶ点だ。CIパイプラインにはDBアクセスが必要になり、新しく入った開発者はコンパイル前にDBを立ち上げなければならない。オフラインモードでクエリメタデータをキャッシュできるが、これは覚えておくべき追加のワークフロー手順だ。

高レベルORM機能はない。リレーションの読み込みもない。eager loadingもlazy loadingもない。自動JOINもない。ネストしたリレーションを持つ複雑なデータモデルなら、すべてのSQLを自分で書くことになる。単純なCRUDなら問題ない。複雑なデータグラフだと、だんだん面倒になる。

オフラインモードには意識的な運用が必要だ。DBなしでビルドしたいなら、cargo sqlx prepare.sqlxファイルを生成する。これらのファイルにはキャッシュされたクエリメタデータが入る。クエリを変更して再生成するのを忘れたら? 古いビルドになる。動きはするが、摩擦はある。

SQLxを選ぶタイミング

  • チームがすでにSQLで考えており、抽象化レイヤーを望んでいない
  • 動的クエリが主要な要件だ
  • 新規プロジェクトで、動くDBコードまでの最短距離がほしい
  • 妥協のない非同期DBアクセスが必要だ

SeaORM: どこか馴染みのあるやつ

最も向いているケース: 非同期と動的クエリを備えた、モダンなORM体験を求める開発者

Django ORM、ActiveRecord、Eloquentを使ったことがあるなら、SeaORMには馴染みを感じるはずだ。そして2026年1月の2.0リリース時点で、これは本当に本番投入可能な状態になった。

SeaORMはDieselとは真逆のアプローチを取る。コンパイル時検証ではなく、ランタイムで動作する。安全性を少し手放す代わりに、他のライブラリでは追いつけない柔軟性を得ている。

SeaORM 2.0が注目に値する理由

リレーションが期待どおりに動く。一対多、多対多、eager loading、lazy loading――SeaORMはすべて処理できる。ユーザー・投稿・コメント・タグのような複雑なデータモデルがあっても、SeaORMなら自然にその関係をたどっていける。DBと格闘している感じがしない。

動的クエリは一級市民だ。オプションのフィルタ? 条件付きソート? ページネーション? SeaORMなら何も意識せずに扱える。クエリビルダーはランタイムで動くので、構造を自由に変えられる。Dieselが苦しむ部分であり、SeaORMが輝く部分でもある。

2.0の機能は本当に実用的だ。Entity LoaderはN+1問題をスマートに解決する。関連エンティティを個別クエリで叩く代わりに、効率よくバッチロードしてくれる。sea-orm-syncはCLIツールやスクリプト向けに同期版を提供する。Nested ActiveModelは複雑な挿入処理をきれいにしてくれる。

エンティティ生成は実際に時間を節約してくれる。sea-orm-cliをDBに向ければ、Rustのエンティティを生成してくれる。スキーマが変わったら? もう一度生成すればいい。派手ではないが、自動化することで手作業の構造体定義に起因するバグを減らせる。

率直な欠点

ランタイムエラーは現実に起こる。DieselやSQLxと違って、SeaORMはスキーマ不整合をコンパイル時には検出しない。カラム名を変えてエンティティ更新を忘れたら? ランタイムエラーだ。これを補うには十分なテストカバレッジが必要になる。

比較的新しい。SeaORM 2.0は安定しているが、エコシステムはまだ小さい。ブログ記事は少なく、Stack Overflowの回答も少なく、「自分も同じ問題に遭遇した」というスレッドも少ない。公式ドキュメントとDiscordへの依存度が高くなる。

わずかなランタイムオーバーヘッドもある。動的にクエリを組み立てるにはコストがかかる。小さい――99%のアプリケーションでは無視できるレベルだ――とはいえ、1マイクロ秒まで絞り出したいなら、DieselやSQLxのほうが速い。

SeaORMを選ぶタイミング

  • エンティティ間の複雑なリレーションを持つWeb APIを作る
  • 動的な検索やフィルタリングが主要機能だ
  • チームがDjango、Rails、Laravel出身で、馴染みのあるパターンを求めている
  • コンパイル時保証より開発速度のほうが重要だ

Rusqlite: 当たり前の選択肢(SQLite向け)

最も向いているケース: CLIツール、デスクトップアプリ、組み込みシステム、そしてSQLiteを使うあらゆるもの

Rusqliteを「ORM」と呼ぶのはかなり好意的な表現だ。これはSQLiteを包むラッパーにすぎない。だがそこが強みでもある――一つのことをやり、それを完璧にこなす。

プロジェクトがSQLiteを使うなら――そして実際、多くのRustプロジェクトがそうだ――Rusqliteは議論の余地なく明白な選択肢になる。

Rusqliteがただただうまく機能する理由

バンドルされたSQLiteが素晴らしい。bundledフィーチャーフラグを有効にすると、RusqliteはSQLiteをバイナリに直接コンパイルする。システム依存は不要だ。「sqlite3-devをインストールしてください」などと言われることもない。バイナリはどこでも動く。何も入っていないマシンにCLIツールを配布したことがあるが、ただ動いた。

ちょうどよく薄い。Rusqliteは賢く振る舞おうとしない。コネクション、プリペアドステートメント、トランザクションを提供し、その上にRustの型安全性を載せる。借用チェッカがリソースの誤用を防ぎ、プリペアドステートメントがインジェクションを防ぐ。それで終わりだ。このライブラリはそれ以上でもそれ以下でもない。

SQLite専用機能にも手が届く。ユーザー定義SQL関数、仮想テーブル、全文検索、JSON拡張――RusqliteならSQLiteの全機能にアクセスできる。汎用ORMはこうした機能を抽象化の裏に隠しがちだが、Rusqliteは直接使わせてくれる。

率直な欠点

SQLite専用だ。PostgreSQLやMySQLが必要なら、Rusqliteは候補に入らない。以上。

ORM的な便利さはない。クエリビルダーもない。リレーション処理もない。マイグレーションもない(もちろんrefineryやrusqlite_migrationは使えるが)。SQL文字列を自分で書き、結果も手動でマッピングする必要がある。

同期専用でもある。Rusqliteは非同期を扱わない。CLIツールやデスクトップアプリなら通常は問題にならない。Webサーバーなら、SQLxのSQLiteサポートを使うか、スレッドプールで包む必要がある。

Rusqliteを選ぶタイミング

  • ローカルストレージが必要なCLIツールを作る
  • 組み込みDBを持つデスクトップアプリケーションである
  • SQLiteが適切なDB選択となるあらゆるプロジェクト
  • DBサーバーをインストールできない環境へデプロイする

実際にどう決めるか

4つすべてを本番で使ったうえで、私の頭の中にある判断フレームワークはこうだ。

SQLiteか? → Rusqlite。以上。悩むな。

コンパイル時SQL検証 + クエリDSLがほしいか? → Diesel。長く生きるコードベースに対しては、最も安全な賭けだ。

コンパイル時検証はほしいが、raw SQLのほうが好きか? → SQLx。安全性は全部入りで、DSLの学習コストはない。

動的クエリとリレーション、モダンな非同期ORMが必要か? → SeaORM 2.0。特にDjangoやRails出身ならなおさらだ。

新規プロジェクトのデフォルト選択は? → たいていDieselから始める。他に理由がないなら。コンパイル時安全性に何度も救われてきた。


不都合な真実

Rustコミュニティで、誰も認めたがらないことが一つある。ほとんどのプロジェクトでは、この中のどれを使ってもちゃんと動く。

どれもよくメンテナンスされている。どれもSQLインジェクションを防いでくれる。どれも、重視するDBに対してきちんと動作する(それぞれの守備範囲の中で)。違いが出るのは周辺部であり、私たちの大半はその周辺部にはいない。

自分の脳の働き方に合うものを選べ。 SQLで考えるならSQLxを使え。コンパイラに面倒を見てほしいならDieselを使え。すでに知っているORMっぽさがほしいならSeaORMを使え。SQLiteならRusqliteを使え。

そして調査はもうやめて、ビルドを始めよう。

まだコメントはありません。

まだコメントはありません。