集計・分析系のSQL機能はPostgreSQLが厚い
ダッシュボードやKPI集計のクエリを書くとき、PostgreSQLはMySQLに無い機能がいくつもあります。
- FILTER句:
COUNT(*) FILTER (WHERE ...)のように条件付き集計を1行で書けます。MySQLはSUM(CASE WHEN ... THEN 1 ELSE 0 END)のような書き方が必要です。 - GROUPING SETS/CUBE:PostgreSQLは9.5から両方に対応しています。MySQLは8.0で
ROLLUPだけ対応し、CUBEとGROUPING SETSには非対応のままです。 - 順序集合集計関数:
PERCENTILE_CONT/PERCENTILE_DISCでパーセンタイルを、MODE() WITHIN GROUP (...)で最頻値を直接求められます。MySQLには無く、中央値の算出もウィンドウ関数での代用が必要です。 - 配列・JSON系の集計:
array_agg/jsonb_aggなど。MySQLのGROUP_CONCATは文字列連結止まりです。
この手引のPostgreSQL運用の考え方で扱っているRLS(行単位セキュリティ)も、PostgreSQL固有の機能でMySQLには相当する仕組みがありません。
センサーデータやアクセスログのような時系列データも、TimescaleDBのような拡張機能によりPostgreSQLのまま強くなる領域です。ただし、時系列データが主役になる規模のシステムでは、ClickHouseなど専用の時系列DBを別立てで検討した方がいい場合もあります。
速度の話は「PgBouncerを挟むかどうか」で変わる
単純な主キー参照が大半を占める、読み取り中心のOLTPワークロードでは、MySQLの方が速いという傾向は実際にあります。MySQLはスレッドごとに接続を扱う軽量なモデルで、PostgreSQLは接続ごとにプロセスを立てるモデルのため、素の状態で大量の同時接続をさばくと、MySQLに分があります。
ただし、これは「PostgreSQLをプーラーなしで直接使った場合」の話です。この手引のPostgreSQL運用の考え方で扱っているPgBouncerを手前に置けば、接続はプールされた少数のバックエンド接続に集約されるため、接続ごとのプロセス生成コストという弱点はそもそも問題になりません。つまり、この手引が最初から推奨している構成を前提にすると、単純接続数の勝負という土俵自体が変わります。逆にPostgreSQLは、書き込みが多いワークロードや、複数テーブルのJOIN、分析的なクエリでMySQLより優位になる傾向があります。
AI用途で埋め込みを扱うならpgvectorが一歩先
MySQLも9.0からベクトル型を持ちますが、機能の成熟度はPostgreSQLの拡張機能pgvectorに及びません。pgvectorはHNSW・IVFFlatという2種類の近似最近傍探索インデックスに対応しており、大量の埋め込みベクトルから類似検索を高速に行えます。MySQLのベクトル型は登場が新しく、同水準のインデックス機能はまだありません。
AIエージェントが生成した文章の埋め込みを保存して類似検索するRAG(検索拡張生成)や、レコメンド機能を個人開発で作る場合、pgvectorはPostgreSQLの通常のテーブルにベクトル列を1つ追加するだけで始められます。新しいデータベース製品を別途学ぶ必要がありません。
結局、この手引がPostgreSQLを選ぶ理由
PostgreSQLが向く
集計・分析クエリを書く、RLSで行単位のアクセス制御をしたい、AI関連の埋め込み検索を将来やりたい場合。この手引の標準構成です。
MySQLが向く
既存システムがMySQL前提、あるいは単純な読み取り中心のOLTPで、PgBouncerのようなプーラーを挟む運用コストすらかけたくない場合。
個人開発の多くはPostgreSQLで問題なく、この手引の他の記事(Next.jsの基礎、PostgreSQL運用の考え方)ともそのままつながります。既存資産や社内標準の都合でMySQLを使う場合も、SQL機能の違いだけは事前に把握しておくと、後から「この集計、MySQLだと書けない」という手戻りを避けられます。