X(Twitter) Zenn GitHub RSS 共有

インデックスに関して

作成日時:2024-09-22
更新日時:2026-03-15

関連:Relational Database

クラスター化インデックス

インデックス上に実データが格納されているもの。
MySQLのInnoDBなど。

カバリングインデックス

付加列インデックス

インデックスキーの列に加えて、非キー列(付加列)をインデックスに含める機能。
key => PK + 追加情報。
効果的にカバリングインデックスを作成できる。

部分インデックス

部分インデックス
特定のカラムにのみ、インデックスを貼る。

CREATE INDEX idx_active_users ON users (username)
WHERE is_active = true;

SELECT username
FROM users
WHERE is_active = true AND username LIKE 'A%';

メリット

論理削除に使えそう

各RDBMSの対応

インビジブルインデックス

MySQL :: MySQL 8.0 リファレンスマニュアル :: 8.3.12 不可視のインデックス

PostgreSQLには(いまのところ)無い。

アダプティブハッシュインデックス

MySQLのinnoDBなどのクラスター化インデックスにおける。
セカンダリインデックスを使用して検索をする場合、

  1. セカンダリインデックスを使用し、PKを取得
  2. プライマリインデックスを使用し、データを取得

と、2段階アクセスが発生し、パフォーマンスがよくない。

この主キー検索を高速化するためにアダプティブハッシュインデックスがある。
イメージとしてはkeyがセカンダリインデックスの検索値のハッシュ、valueがレコードへのポインター。
ハッシュなので等価検索のときにのみ使われる。
バッファプール上に作られる。

GROUP BY におけるインデックススキャン

{GROUP BY 指定カラム, 集計対象値}でインデックスを貼っているとした時、下記のスキャンが行われる。

タイトインデックススキャン

インデックスを使用してGROUP BYクエリを解決

ルースインデックススキャン

集計対象値のMINやMAXならば、各GROUP BY指定カラムの先頭のインデックスデータを見ればすぐわかる。

(A, 1),(A, 2),(A, 3),(B, 4),(B, 5)
ならば先頭のカラムの値、つまり1と4のカラムだけを見ればいいから
パフォーマンスはよい。

MIN()を取ろうとすれば、A1,B4が返却される。

データ構造

4. MVCCとストレージ構造 · PostgreSQL Internals

ページがツリー構造になっている。

ルートノード -> インターナルノード -> リーフノード

Index Skip Scan

PostgreSQL 18以降。
複合B-treeインデックスにおいて、検索条件に先頭カラム以外の項目を指定しても、検索時にインデックスが使用される。

部分インデックスとカバリングインデックスによる高速化

特定の店舗の行数が多すぎて、JOINに時間がかかる場合など。
その店舗のレコードを対象とし、結合するカラムと取得するカラムを持つインデックスを作ればいい。
INDEX ONLY SCANとなる。

CREATE INDEX idx_partial_covering 
ON あなたのテーブル (検索カラム) 
INCLUDE (結合に使うカラム, SELECTするカラム)
WHERE 検索カラム = '特定の値';

INCLUDEにより、インデックスの階層構造を減らせる。
「検索の効率化」と「インデックスの肥大化抑制」
INCLUDEのカラムは比較対象ではなく、ただの付随するデータ。

(A) INCLUDE (B, C)においてインデックスはAのみで階層が作られる。
(A,B) INCLUDE (C)においてインデックスはA*Bで階層が作られる。