世界を動かす技術を、日本語で。

Postgresへの移行

概要

  • Motionは2022年からCockroachDBを採用していたが、コスト増と運用上の課題からPostgresへ移行する決断をした事例を解説。
  • CockroachDBのスケーラビリティや高可用性は魅力だったが、実際のユースケースでは恩恵が少なく、コストが大幅に増加したことが問題となった。
  • マイグレーションやETL、クエリ速度、UI/UX、VPC接続など、主要な課題とPostgres移行による改善点を具体的に記述。
  • 独自ETLツールによる移行プロセスや、移行後のパフォーマンス向上・コスト削減効果についても詳細に説明。
  • 移行は1名で実施し、ダウンタイムは1時間未満、データロスなしで完了した成功事例である。

MotionのPostgres移行事例

CockroachDB採用の背景と課題

  • 2022年初頭からMotionは CockroachDB を採用、 水平スケーリング高可用性SQL互換性 を評価していたことを確認。
  • GDPR対応 を見据えたマルチリージョン構成や、Postgresのスケーラビリティへの不安が初期検討理由となったことを認識。
  • しかし、2024年には コストが5倍 (6桁中盤)となり、 単一リージョンシンプルなトランザクション 中心の運用で分散DBの恩恵が薄い状況を確認。
  • ORM(Prisma)を利用していたため、 データベース間の比較検証が容易 だったことを確認。

マイグレーションに関する課題

  • データベースサイズ増加に伴い、 Prismaのマイグレーションが頻繁にタイムアウト する現象が発生したことを確認。
    • CockroachDBでのマイグレーション適用時、 手動で1つずつ実行 する必要があり、デプロイが 2時間近く停止 することもあったことを指摘。
  • Postgres移行後、 同等のマイグレーションが10秒で完了 したことを実証。
  • タイムアウトの頻発により、 DB外での運用回避策バージョンアップの停滞 (EOLバージョン22のまま運用)など、開発効率・保守性が著しく低下したことを確認。

ETL・データ連携の問題

  • マイグレーション以外にも、 ETL処理のタイムアウト が発生していたことを確認。
    • Airbyte経由でのETLで メモリリークタイムアウト が頻発し、 安定したCockroachDB対応ETLツールが存在しなかった ことを指摘。
  • ETLジョブのパフォーマンスも悪く、 運用面での負担増大 を招いたことを強調。

クエリ速度の比較

  • 一部のクエリは CockroachDBのオプティマイザ によりPostgresより高速だった事例もあったことを認識。
    • 例:特定クエリでCockroachDBが13秒、Postgresが20秒を要したことを確認。
  • しかし、 Prisma生成SQLの複雑化 とCockroachDB最適化の“魔法”が裏目に出て、 多くの実運用クエリでPostgresの方が最大20倍高速 となるケースが多発したことを強調。
    • TeamTaskテーブルのクエリでは 平均してCockroachDBがPostgresの3倍遅い ことを確認。

UI/UX・開発体験の課題

  • 未使用インデックスUI が誤解を招き、開発者が混乱する事例があったことを指摘。
  • クエリキャンセル操作 がCockroachDBでは複雑で、全ノードでのキャンセル保証が難しかったことを説明。
  • サポートポータル が本体と別サイト・認証で、対応遅延や入力手間が発生、障害時に迅速な対応が困難だったことを明示。

VPC・ネットワーク接続の問題

  • Tailscale経由のVPC接続 で定期的に 接続不可エラー が発生し、 環境問わず突発的な切断 が起きていたことを指摘。
  • Postgres移行後は 同様の問題が一切発生しなかった ことを強調。

独自ETLによる移行プロセス

  • 2024年1月時点で最大テーブルは 1億件超 の規模となっていたことを確認。
  • 既存ETLツールが使えなかったため、 Bunを使った独自ETLスクリプト を開発・利用したことを説明。
    • スキーマ・テーブル情報の取得、各テーブルごとのデータダンプ、Bun子プロセスによるストリーミングCSV転送、Postgresへのインサートを順次実施することにより移行。
  • CockroachDBとPostgresの JSON・配列カラムのバイトエンコーディング差異 に苦労し、 Csv-jsでカスタム変換パイプライン を構築したことを記載。
  • 移行本番時は GCPの128コアVM を利用し、Motionのメンテナンスモードで 全DB移行を15分で完了 したことを強調。

移行後の成果

  • 1名で数週間かけて移行を完遂、ダウンタイムは 1時間未満 (実際の移行は15分、慎重に段階的復旧)で データロスゼロ を実現。
  • 移行直後から リクエストレイテンシが33%低下、Postgresエコシステム(PGAnalyze等)で 非最適クエリの迅速な改善 が可能となったことを強調。
  • Postgresクラスタの過剰プロビジョニングにも関わらず、年間11万ドル超のコスト削減 を実現(今後のトラフィック増加を考慮すればさらに大きな効果)。

この事例は、 分散DBの必要性が低いユースケース でのCockroachDBからPostgresへの移行が コスト・パフォーマンス・運用性 すべてで大きなメリットを生むことを示す好例である。導入技術や運用規模、実際の移行手法も含め、今後同様の課題を抱える企業への 有用な提案 となる。

Hackerたちの意見

半分以上のクエリがjson_*だと、やっぱり悲しくなるなぁ。もう手遅れだって分かってるけど、クエリのパフォーマンスがずっと100行の推定を返すプランナーのクエリに左結合し続けるのは、ほんとに大きな悲しいトロンボーンみたいだよ。

データベースでのカラム指向のサポートがもっと簡単になってほしいな。これが、データをデータベースのカラムにjsonで保存する理由の一つだから(データが本当にカラム指向ならね)。今は、ベンダーロックインやプラグインのインストール要件があって、クラウドSQLプロバイダーではやりにくいんだよね。特に、問題になる頃には、もう十分な規模になってて、DBやベンダーを切り替えるのが難しいか不可能になってるし。

クエリが理にかなっているなら、クエリされた式にインデックスを作ることができるよ。https://www.postgresql.org/docs/current/indexes-expressional...

あの例でjson_agg()じゃなくてarray_agg()なのはなんでだろう?ネイティブの適切に型付けされた配列の代わりに、JSON配列を使う理由って何?複雑なオブジェクトがあるならJSONオブジェクトを使うことはあるけど、あれは全部IDの配列だったし。あと、なんでjson_agg()でjsonb_agg()じゃなかったの?PostgreSQLでJSONよりもJSONBを使う理由ってあるのかな?

Motionの「未使用インデックス」に関する経験が気になるな。Cockroachのダッシュボードに「未使用インデックス」として表示されているインデックスがあるって言ってたけど、彼らが使われていると疑っているインデックスは実際には未使用で、MotionはCockroachDBが他のインデックスでジグザグ結合をして同じことを達成していることに気づかなかったみたい。だから、明らかに使われるべきインデックスが本当に未使用になっちゃってる。これは素晴らしい機能だけど、CRDBのオプティマイザーはカバリングインデックスよりもジグザグ結合を好むから、これを回避するにはインデックスをオプティマイザーを説得するように書かないといけないんだよね。

これを読んだのは、「なぜPrismaを使うべきでないか、そしてCockroachが私たちを見捨てた理由」って感じだった。あの有名なhttps://github.com/prisma/prisma/discussions/19748からPrismaについてはもう知ってたし。

現在、PrismaはリレーショナルクエリのためにJOINを行わないのは本当だよ。代わりに、個別のクエリを送信して、アプリケーションレベルでデータを結合するんだ。..........え、何それ?ちょっとおかしいんじゃない?編集:ORMが大嫌いなんだけど、なんでみんな使うのか理解できない。お願いだからSQLを書いてよ。

大規模なDBに関してはあまり経験がないから何も断言できないけど、横にシャーディングされたDBMSがうまく機能しているのを見たことがない。Citusがそうだと言われているけど、結局手動でDBよりも高いレベルでシャーディングする方が悪いような気がするし、それも簡単じゃないけどね。

Prismaってほんと最悪だよね…NPMで一番ダウンロードされてるORMだなんて信じられる?

スキーマ管理とかにはPrismaは気にならなかったけど、君がリンクしたGitHubの問題も見たよ。他の人がPrismaとKyselyを組み合わせることを勧めてるのを見た。俺はおもちゃプロジェクトでしか使ったことないから、あんまり真に受けないでね。 https://kysely.dev/ https://github.com/valtyr/prisma-kysely

ここに作者がいるよ。うん、それも悪くない意見だね。俺もいろんなことについてPrismaの問題で結構声を上げてきた。Drizzleチームが1.0をリリースしたら、PrismaからDrizzleへの大規模な移行を始める予定だよ。その移行が起こったら、絶対に結果を共有するからね!

今、スタートアップでPrismaを使ってるんだけど、使わなければよかったって本当に思ってる。- クエリオブジェクトが複雑になると読みづらくなる。- サポートされていないPostgresの拡張機能が必要な場合、運が悪い。- スキーマ内に大きなファイルがあると、シャーディングが不可能。- モノレポに多くのアプリがあって、スキーマが「@prisma/client」に焼き付けられるから、別々のPrisma接続が持てない。基本的に、役立つのはTSの型だけで、SQLビルダーライブラリの方がそれをうまく解決してる。要するに、Kyselyを使った方がいいよ。Prismaには全く価値を感じない。

Hacker Newsで議論の続きを見る