カテゴリ: データベース 更新日: 2026/04/06

SQL GROUP BYのパフォーマンス改善ガイド!重い処理を高速化する初心者向け対策

GROUP BYでパフォーマンスが落ちる理由と対策
GROUP BYでパフォーマンスが落ちる理由と対策

先生と生徒の会話形式で理解しよう

生徒

「先生、最近データベースの勉強をしているのですが、データをグループ分けして計算する『GROUP BY』という命令を使うと、なんだか処理に時間がかかる気がするんです。」

先生

「よく気づきましたね!実はGROUP BYは、正しく使わないとコンピュータにとても大きな負担をかけてしまう、ちょっと『重い』命令なんです。」

生徒

「どうして重くなるんですか?ただ仲間外れを探したり、同じ種類でまとめたりするだけですよね?」

先生

「そう思うかもしれませんが、コンピュータの裏側では、膨大なデータの並べ替えや、一時的なメモ作成が頻繁に行われているんですよ。今日は、なぜ遅くなるのか、どうすれば速くなるのかを、初心者の方でもわかるようにじっくり解説しますね。」

1. SQLとは何か?

1. SQLとは何か?
1. SQLとは何か?

SQL(エスキューエル)は、データベースと呼ばれる「大量のデータを整理して保存する箱」に対して指示を出すための言語です。例えば、お店の売上リストの中から「先月は何が一番売れたかな?」と探したり、学校の生徒名簿に「新入生を追加」したりするときに使います。

パソコンを触ったことがない方でも、「魔法の注文書」だと思えば簡単です。決められたルールで注文書を書けば、データベースという有能な執事が、瞬時に結果を持ってきてくれます。その注文書の中でも、特定の項目ごとに集計を行うのが今回紹介する「GROUP BY」です。

エンジニアの必須スキル「SQL」を、 図解と豊富な練習問題でゼロから体系的に学びたい人へ。 MySQLやPostgreSQLなど、各種データベースに対応した不朽の入門書です。

SQL 第2版 ゼロからはじめるデータベース操作をAmazonで見る

※ Amazon広告リンク

2. GROUP BY(グループバイ)の仕組みを知ろう

2. GROUP BY(グループバイ)の仕組みを知ろう
2. GROUP BY(グループバイ)の仕組みを知ろう

「GROUP BY」は、その名の通り「グループごとに分ける」ための命令です。例えば、バラバラに記録された「果物の販売記録」から、「りんご」「みかん」「ぶどう」という種類ごとに売れた個数を合計したいときに使います。

ここで、「テーブル」という用語を覚えましょう。テーブルとは、Excel(エクセル)のような「表」のことです。

用語解説:レコード
テーブル(表)の「1行分」のデータのことを指します。例えば、1回のお買い物の記録が1レコードになります。

まず、以下のような「sales(売上)」テーブルがあるとしましょう。


id | product_name | amount | sale_date
---+--------------+--------+------------
1  | りんご       | 100    | 2024-01-01
2  | みかん       | 50     | 2024-01-01
3  | りんご       | 150    | 2024-01-02
4  | ぶどう       | 200    | 2024-01-02
5  | みかん       | 80     | 2024-01-03
6  | りんご       | 120    | 2024-01-03

この表から「商品名(product_name)ごとに売上の合計(amount)を出したい」場合、以下のようなSQLを書きます。


SELECT product_name, SUM(amount)
FROM sales
GROUP BY product_name;

この命令を実行すると、コンピュータは裏側で以下のような作業をします。

  1. 「product_name」の列を見て、同じ名前のものを探す。
  2. 「りんご」は1番、3番、6番だな、と分類する。
  3. 分類したグループごとに、金額を足し算(SUM)する。

結果は以下のようになります。


product_name | SUM(amount)
-------------+------------
りんご       | 370
みかん       | 130
ぶどう       | 200

3. なぜGROUP BYでパフォーマンス(速度)が落ちるのか?

3. なぜGROUP BYでパフォーマンス(速度)が落ちるのか?
3. なぜGROUP BYでパフォーマンス(速度)が落ちるのか?

データが数件なら一瞬ですが、これが数百万件、数千万件になると話が変わります。パフォーマンスが落ちる(動作が重くなる)主な理由は3つあります。

① 並べ替え(ソート)の負担

コンピュータがグループ分けをする際、実は最初にデータをバラバラの状態から「同じ種類が隣り合うように並べ替える」という作業をすることが多いです。図書館のバラバラの本を、著者名ごとに棚に並べ直す作業を想像してください。本が100万冊あったら、並べるだけで日が暮れてしまいますよね。

② 一時テーブルの作成

集計作業中に、コンピュータは「計算用のメモ用紙」をメモリ(一時的な記憶場所)に作ります。データが多すぎると、このメモ用紙が足りなくなり、処理が極端に遅くなります。

③ 全走査(フルスキャン)

「どこに何があるか」という目次がない状態で、1行目から最後の行まで全部チェックすることを「フルスキャン」と言います。1,000ページある辞書を、目次なしで一文字ずつ探していくようなものです。

4. パフォーマンスを劇的に上げる対策:インデックスの活用

4. パフォーマンスを劇的に上げる対策:インデックスの活用
4. パフォーマンスを劇的に上げる対策:インデックスの活用

一番の解決策は、「インデックス(索引)」を作ることです。インデックスとは、本でいうところの「索引」や「目次」です。

あらかじめ「商品名(product_name)」にインデックスを貼っておくと、データベースはどこに「りんご」があるかを最初から知っているため、並べ替えの手間を大幅にカットできます。

注意点:
インデックスは魔法ではありません。何でもかんでもインデックスを作ると、今度は「データの追加(保存)」が遅くなるという副作用があります。必要な列にだけ作りましょう。

5. 実践:WHERE句を使ってデータを絞り込む

5. 実践:WHERE句を使ってデータを絞り込む
5. 実践:WHERE句を使ってデータを絞り込む

もう一つの重要なテクニックは、「グループ分けをする前に、計算するデータ自体を減らす」ことです。

例えば、「2024年1月2日以降のデータだけを集計したい」場合、全部をグループ分けしてから日付を見るのではなく、先に日付で切り捨ててからグループ分けをします。


SELECT product_name, SUM(amount)
FROM sales
WHERE sale_date >= '2024-01-02'
GROUP BY product_name;

実行結果(元のテーブルから1月1日のデータを除外して集計):


product_name | SUM(amount)
-------------+------------
りんご       | 270
みかん       | 80
ぶどう       | 200

このように、WHERE(ウェア)を使ってあらかじめ行数を減らすことで、コンピュータの並べ替え作業や計算の負担を大幅に軽減できます。これは、お掃除をする前に「明らかなゴミを捨ててから整理整頓する」のと同じくらい効率的な方法です。

6. よくある間違い:HAVINGとWHEREの違い

6. よくある間違い:HAVINGとWHEREの違い
6. よくある間違い:HAVINGとWHEREの違い

初心者がハマりやすいのが、HAVING(ハビング)という命令の使い方です。

  • WHERE:グループ分けをする「前」にデータを絞り込む(速い!)
  • HAVING:グループ分けをして計算した「後」に結果を絞り込む(遅くなりやすい)

「売上合計が200円以上の商品だけ表示したい」という場合は、計算が終わらないと分からないのでHAVINGを使います。


SELECT product_name, SUM(amount)
FROM sales
GROUP BY product_name
HAVING SUM(amount) >= 200;

product_name | SUM(amount)
-------------+------------
りんご       | 370
ぶどう       | 200

可能な限りWHEREでデータを削り、どうしても計算後の数値で絞り込みたい時だけHAVINGを使う。これがプロが意識している「高速化のコツ」です。

7. データベースを「重く」しないための心構え

7. データベースを「重く」しないための心構え
7. データベースを「重く」しないための心構え

SQLを書くときは、常に「コンピュータに無駄な汗をかかせない」ことを意識しましょう。

データが少ないうちはどんな書き方をしても動きますが、サービスが成長してユーザーが増えると、一通りの不適切なSQLが原因でサイト全体が止まってしまうこともあります。

今回の内容をおさらいすると、 まず第一に、集計対象の列に「インデックス」があるかを確認すること。 第二に、WHEREを使って、少しでも処理する対象の行(レコード)を減らすこと。 第三に、不必要な列までグループ化に含めないことです。

これらを意識するだけで、あなたのSQLは驚くほどスムーズに動くようになります。最初は難しく感じるかもしれませんが、紙に図を書いてデータの流れをイメージしてみるのが、上達への一番の近道ですよ。

カテゴリの一覧へ
新着記事
New1
Rails
Railsのルーティングテストを完全ガイド!初心者でもわかるrouting specとpath helperの検証方法
New2
データベース
SQL GROUP BYのパフォーマンス改善ガイド!重い処理を高速化する初心者向け対策
New3
Ruby
Rubyのテストしやすい分岐の書き方!条件抽出・依存注入・網羅性を初心者向けに解説
New4
Rails
Railsのログ設定を完全理解!初心者でもわかる構造化ログ・Request ID・logrageの使い方
人気記事
No.1
Java&Spring記事人気No1
データベース
SQLで複数テーブルを結合する方法を徹底解説!初心者でも図解でわかるJOINと集計の基本
No.2
Java&Spring記事人気No2
Rails
Hotwire超入門:Turbo Drive / Turbo Frames / Turbo Streams を一気に理解【Rails 7 / Rails 8】
No.3
Java&Spring記事人気No3
Ruby
WindowsでRubyをインストールする方法!RubyInstallerとMSYS2を使った完全ガイド
No.4
Java&Spring記事人気No4
データベース
PostgreSQLが遅い原因を解決!初心者向けデータベースチューニングと高速化の基本
No.5
Java&Spring記事人気No5
Rails
Rails 7/8対応|RSpec入門:describe・context・it・expectを初心者向けに完全解説
No.6
Java&Spring記事人気No6
Ruby
Rubyの条件分岐をスッキリ!早期リターンとガード節で読みやすいコードへ
No.7
Java&Spring記事人気No7
データベース
データベース設計の要!外部キー(Foreign Key)とは?初心者向けに徹底解説
No.8
Java&Spring記事人気No8
Ruby
Ruby配列の抽出と条件処理を完全解説!select・reject・take・dropの定番パターン