6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQLのパフォーマンスを知る

Last updated at Posted at 2025-03-05

はじめに

この記事は、SQLのパフォーマンスに関するお話です。

事前準備

以下のテーブルを準備します。

DDL
create table if not exists public.users
(
    id                 integer                                            not null primary key,
    login_id           varchar(50)                                        not null,
    name               varchar(255)                                       not null,
    branch_id          integer                                            not null,
    created_at         timestamp                                          not null
);


create table if not exists public.branches
(
    id                 integer                                            not null primary key,
    name               varchar(255)                                       not null,
    created_at         timestamp                                          not null
);

■ユーザーテーブル(users)

ID(id) ログインID(login_id) 名前(name) 支店ID(branch_id) 登録日時(created_at)
1 user1 ユーザー1 1 2025-02-04T12:00:00
2 user2 ユーザー2 1 2025-02-04T13:00:00
3 user3 ユーザー3 2 2025-02-04T14:00:00

■支店テーブル(branches)

ID(id) 名前(name) 登録日時(created_at)
1 fugafuga支店 2025-02-04T12:00:00
2 hogehoge支店 2025-02-04T13:00:00

検証内容

fugafuga支店のユーザーを検索する。

サンプル1(一般的なSQL)

一般的なSQL
SELECT
    users.*
FROM users
INNER JOIN branches ON
    branches.id = users.branch_id
WHERE
    branches.name = 'fugafuga支店';

サンプル2(JOIN条件で絞り込むSQL)

JOIN条件に変更したSQL
SELECT
    users.*
FROM users
INNER JOIN branches ON
        branches.id = users.branch_id
    AND branches.name = 'fugafuga支店';

パフォーマンスの比較

■計算量(𝑂)

クエリ インデックスなし インデックスあり
サンプル1 𝑂(n x m) 𝑂(n)
サンプル2 𝑂(n x m) 𝑂(n)(より速い)

ポイント:
インデックスがない場合: 両方のクエリは同じ計算量です 𝑂(𝑛 × 𝑚)
インデックスがある場合: サンプル2のクエリの方が速くなります。

理由:
JOINの段階で「branches.name = 'fugafuga支店'」の条件が適用されるため、無駄なループが減ります。
一方、サンプル1では、まず全ての「users」と「branches」を結合し、その後に「WHERE」で絞り込むため、より遅くなります。

考察

クエリ 処理のタイミング パフォーマンス
サンプル1 結合後に「branches.name = 'fugafuga支店'」を適用 結合後にフィルタリング (遅い)
サンプル2 JOINの段階で「branches.name = 'fugafuga支店'」を適用 JOINの段階で絞り込み(より速い)

推奨:

  • 大規模なデータセットの場合、サンプル2を使用する方が「パフォーマンス」が良いです
  • 特に、branches.id と branches.name にインデックスがある場合、サンプル2は「大幅に高速化」されます
6
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?