KDOC 643: WHERE条件の大小によって実行計画が変わる例
この文書のステータス
- 作成
- 2026-10-05 貴島
- レビュー
- 2026-10-05 貴島
概要
推定した取得行数によって、全部読むか一部だけ読むかの判断が変わって実行計画が変わるのを見る。
CREATE TABLE users (
id integer PRIMARY KEY,
name varchar(255)
);
-- 10万件を挿入する。id の物理的な並びをばらばらにする
INSERT INTO users (id, name)
SELECT
i,
-- 32x2 文字
concat(md5(random()::text), md5(random()::text))
FROM generate_series(1, 100000) i
ORDER BY random();
-- 統計情報を作る
ANALYZE users;
-- 1件
EXPLAIN SELECT * FROM users WHERE id < 2;
-- 約1000件
EXPLAIN SELECT * FROM users WHERE id < 1000;
-- 約70000件
EXPLAIN SELECT * FROM users WHERE id < 70000;
| |
|--------------------------------------------------------------------------|
| > CREATE TABLE users ( |
| > id integer PRIMARY KEY, |
| > name varchar(255) |
| > ); |
| CREATE TABLE |
| |
| > INSERT INTO users (id, name) |
| > SELECT |
| > i, |
| > -- 32x2 文字 |
| > concat(md5(random()::text), md5(random()::text)) |
| > FROM generate_series(1, 100000) i |
| > ORDER BY random(); |
| INSERT 0 100000 |
| |
| > ANALYZE users; |
| ANALYZE |
| |
| > EXPLAIN SELECT * FROM users WHERE id < 2; |
| QUERY PLAN |
| Index Scan using users_pkey on users (cost=0.29..8.31 rows=1 width=69) |
| Index Cond: (id < 2) |
| |
| > EXPLAIN SELECT * FROM users WHERE id < 1000; |
| QUERY PLAN |
| Bitmap Heap Scan on users (cost=23.70..1248.40 rows=956 width=69) |
| Recheck Cond: (id < 1000) |
| -> Bitmap Index Scan on users_pkey (cost=0.00..23.46 rows=956 width=0) |
| Index Cond: (id < 1000) |
| |
| > EXPLAIN SELECT * FROM users WHERE id < 70000; |
| QUERY PLAN |
| Seq Scan on users (cost=0.00..2485.00 rows=69782 width=69) |
| Filter: (id < 70000) |
関連
抽象。
- 対象の量の見積もりで、全部読むか一部だけ読むかの方針が切り替わる
関連。
- 参照: 14.1. EXPLAINの利用
- 類似: KDOC 496: 検索も結果もインデックスで完結するとIndex Only Scanになる。実行計画に関する話題
- 具体例: KDOC 640: 関連が少ないレコードで破壊的に時間がかかる現象。入力の値で実行計画が切り替わる実例
- 補足: KDOC 641: 大きなテーブルだとANALYZEで生成される統計情報はテーブルのランダムな標本から取り出される。計画の切り替えの元になる行数の見積もりが、標本から作られて揺れること