シーケンシャルスキャンとインデックススキャン
シーケンシャルスキャンで十分な場合、インデックススキャンが必要な場合、そしてプランナーがどのように判断するかを理解します。
「シーケンシャルスキャンとインデックススキャン」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。
行を見つける 2 つの方法
データベースには、行を読み取る基本的な方法が 2 つあります。
- Sequential Scan — テーブルのすべてのページを読み取ります
- Index Scan — インデックスをたどり、一致する行を取得します
Sequential Scan が適している場合
テーブルの大部分が必要な場合は、インデックスを読み取り、さらに一致する各行を取得するより、テーブルをスキャンする方が安価です。おおよその目安は、行の約 10〜20% を超える場合は seq scan が有利です。
Index Scan が有利な場合
選択性の高いクエリ(行のごく一部だけを取得するクエリ)では、インデックスが効果を発揮します。
EXPLAIN SELECT * FROM users WHERE id = 42;
-- Index Scan using users_pkey (cost=0.43..8.45 rows=1)
EXPLAIN SELECT * FROM users WHERE active;
-- Seq Scan on users (cost=0.00..15000.00 rows=950000)
-- (because most users are active)Index Scan と Index-Only Scan
必要な列がすべてインデックスだけに含まれていて、テーブルを取得する必要がない場合があります。これが Index-Only Scan です。
CREATE INDEX users_email_id_idx ON users(id) INCLUDE (email);
EXPLAIN SELECT email FROM users WHERE id = 42;
-- Index Only Scan using users_email_id_idxBitmap Index Scan
選択性が中程度の場合、PostgreSQL は一致する行のビットマップを作成し、物理的な順序で行を取得することがあります。これにより、ランダム I/O より高速になります。
EXPLAIN SELECT * FROM orders WHERE status = 'pending';
-- Bitmap Heap Scan on orders
-- Recheck Cond: (status = 'pending')
-- -> Bitmap Index Scan on orders_status_idxPlanner が Seq Scan を選ぶ理由
一般的な理由は次のとおりです。
- 検索対象の列にインデックスがありません
- インデックスを使用できません(列に対する関数、OR 句、型の不一致など)
- 予想される行数が多く、インデックスを使うメリットがありません
- 統計情報が古く、Planner が選択性を誤って判断しています
インデックスの使用を強制する場合の注意
PostgreSQL には直接ヒントを指定できません。代わりに次の方法を使います。
- ANALYZE を実行して統計情報を更新します
- 適切なインデックスを追加します
- セッション設定を変更します。診断目的で
SET enable_seqscan = off;を使用できます(本番環境では使用しません)
インデックスを使用できる述語
インデックスの効果を得るには、WHERE 句が「sargable」である必要があります。つまり、インデックス対象の列を直接比較します。
-- GOOD:
WHERE created_at >= '2024-01-01'
-- BAD (function on the column):
WHERE date_trunc('day', created_at) = '2024-01-01'
-- BAD (cast):
WHERE created_at::DATE = '2024-01-01'
-- FIX: add a functional index, or rewrite with range.複合インデックスの順序
(a, b) に対するインデックスは、a 単独のクエリと a AND b のクエリには役立ちますが、b 単独のクエリには役立ちません。
インデックスのサイズが重要な理由
よく使うキーを持つ細い B-tree インデックスは、全体をメモリに保持できる場合がありますが、幅の広いインデックスでは難しいことがあります。小さいインデックスほど高速です。
プランを確認する
インデックスを追加したら EXPLAIN ANALYZE を実行し、Planner が実際に使用していることを確認します。使用されていなければ、原因を詳しく調べます。
まとめ
Sequential Scan と Index Scan の選択は、選択性によって決まります。
- 選択性の高いフィルター → Index Scan
- テーブルの大部分を取得 → seq scan
- 中間の場合 → Bitmap Scan
- sargable かどうかに注意します
確認問題
既存のインデックスがあるのに、PostgreSQL が Sequential Scan を選ぶのはなぜですか。
よくある質問
「シーケンシャルスキャンとインデックススキャン」レッスンは無料ですか?
はい。「シーケンシャルスキャンとインデックススキャン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。
「シーケンシャルスキャンとインデックススキャン」で何を学びますか?
シーケンシャルスキャンで十分な場合、インデックススキャンが必要な場合、そしてプランナーがどのように判断するかを理解します。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「シーケンシャルスキャンとインデックススキャン」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Academyレッスンでコードを書いて実行できますか?
はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- EXPLAINとEXPLAIN ANALYZEの読み方
- シーケンシャルスキャンとインデックススキャン
- Hash Join、Merge Join、Nested Loop
- 遅いクエリの特定と修正