0Pricing
SQL Academy · レッスン

部分インデックスと式インデックス

WHERE句で必要な行だけをインデックス化し、計算式(lower(email)、date_trunc('day', ts))もインデックス化します。

「部分インデックスと式インデックス」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。

部分インデックス: 一部の行だけをインデックス化

部分インデックスは、インデックス作成時にWHERE句に一致する行だけを対象にします。小さく高速で、頻出するクエリに適しています。

CREATE INDEX users_active_email_idx
  ON users(email)
  WHERE deleted_at IS NULL;

部分インデックスが効果を発揮する場合

次のような場合に使用します。

  • 常に同じ述語でフィルタする場合(例: 論理削除)
  • ある値が列の大部分を占める場合(例: 95%の行のstatusが'closed')
  • キャッシュに常駐する小さく高速なインデックスが必要な場合

例: アクティブなセッション

ほとんどのセッションが期限切れで、アクティブなセッションだけを検索する場合です。

CREATE INDEX sessions_active_idx ON sessions(user_id)
  WHERE expires_at > NOW();
-- Caveat: planner can't use NOW() in the index predicate — use a fixed timestamp
-- and reindex periodically, OR use a boolean column.

よりよい方法: 安定した述語を使う

インデックスの述語はIMMUTABLEでなければなりません。時間に依存する式(NOW())は使用できません。代わりにis_activeのような列を使います。

CREATE INDEX sessions_active_idx ON sessions(user_id)
  WHERE is_active = true;

-- The query must use the same predicate to match the index:
SELECT * FROM sessions WHERE is_active = true AND user_id = 42;

式インデックス

列に対する関数の結果をインデックス化します。

CREATE INDEX users_email_lower_idx ON users(LOWER(email));

SELECT * FROM users WHERE LOWER(email) = LOWER('Alice@Example.com');
-- Uses the expression index.

<ul><li>大文字と小文字を区別しない検索には<code>LOWER(email)</code></li><li>計算結果によるソートには<code>(price * tax_rate)</code></li><li>日次レポートには<code>date_trunc('day', created_at)</code></li><li>JSONBからの抽出には<code>(data ->> 'user_id')::BIGINT</code></li></ul>

  • LOWER(email)で大文字と小文字を区別しない検索
  • (price * tax_rate)で計算結果によるソート
  • date_trunc('day', created_at)で日次レポートを作成
  • (data ->> 'user_id')::BIGINTでJSONBから値を抽出

式はIMMUTABLEでなければならない

式にはIMMUTABLEが指定されていなければなりません。つまり、結果が入力だけに依存する必要があります。RANDOM()、NOW()、CURRENT_USERは使用できません。

部分インデックスと式インデックスの組み合わせ

両方を組み合わせることもできます。

CREATE INDEX articles_active_title_idx
  ON articles(LOWER(title))
  WHERE published_at IS NOT NULL;

一意部分インデックス

典型的な「アクティブな行を1つだけにする」パターンです。

CREATE UNIQUE INDEX users_one_active_email
  ON users(email)
  WHERE deleted_at IS NULL;

-- Same email can exist many times in deleted users, but only once active.

インデックスの述語はクエリと一致させる

プランナーは、クエリのWHERE句がインデックスの述語を「含意する」場合にだけ、部分インデックスを使用します。

-- Index:  WHERE is_active = true
-- Match:  WHERE is_active = true AND user_id = 42       ✓
-- Match:  WHERE is_active AND user_id = 42             ✓
-- No:     WHERE user_id = 42                           ✗
-- No:     WHERE is_active IS NOT FALSE                 ✗ (logically same but planner may not realise)

使いすぎない

互いに異なる部分集合を対象とする部分インデックスを多数作成すると、書き込みが遅くなることがあります(INSERTのたびに、該当するすべてのインデックスを更新する必要があります)。頻繁に使うクエリに限定して使用してください。

まとめ

部分インデックスと式インデックスは、1バイトあたりの効果を高めます。

  • 部分インデックス: 検索する部分集合だけをインデックス化する
  • 式インデックス: 計算値をインデックス化する
  • どちらにもIMMUTABLEな述語が必要
  • 一致させるには、クエリでも同じ述語を使用する必要がある

理解度チェック

メールアドレスを大文字と小文字を区別せずに検索したい場合、最も効率的なインデックスはどれですか。

よくある質問

「部分インデックスと式インデックス」レッスンは無料ですか?

はい。「部分インデックスと式インデックス」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。

「部分インデックスと式インデックス」で何を学びますか?

WHERE句で必要な行だけをインデックス化し、計算式(lower(email)、date_trunc('day', ts))もインデックス化します。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

SQL Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「部分インデックスと式インデックス」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSQL Academyレッスンでコードを書いて実行できますか?

はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. B-tree、Hash、GiST、GINインデックス
  2. 複合インデックスと列の順序
  3. 部分インデックスと式インデックス
  4. インデックスのメンテナンスと肥大化
← SQL Academyに戻る