はじめに
この記事は、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は「大幅に高速化」されます