0Pricing
SQL Interview Prep · レッスン

B-Treeインデックスとその効果

インデックスに実際に何が保存され、どの操作が高速化されるかを学びます。

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

面接官がインデックスについて質問する理由

面接官が「このクエリは遅いです。どうしますか」と尋ねたとき、ほぼ必ず期待している答えにはインデックスが含まれます。インデックスは読み取り性能を改善するうえで最も効果の大きい手段なので、構文を暗記しただけの候補者と、データベースが実際にどのように行を見つけるかを理解している候補者を見分ける材料になります。

このレッスンでは、B-Treeインデックスについて正確なメンタルモデルを身につけます。何を格納し、どの操作を高速化し、シニアエンジニアらしくどのように説明するかを学びます。

インデックスが解決する問題

インデックスがない場合、条件に一致する行を見つけるには、データベースはテーブルのすべての行を読み取らなければなりません。これはシーケンシャルスキャン(またはフルテーブルスキャン)です。100万行のテーブルでは、たとえ一致する行が1行だけでも、100万行をチェックすることになります。

インデックスは、値をソートして保持する独立したデータ構造です。すべてのページを読まなくてもトピックを見つけられる本の索引と同じように、データベースエンジンが一致する行へ直接移動できるようにします。

-- No index: the engine reads ALL rows to find this one
SELECT * FROM users WHERE email = 'ada@example.com';

B-Treeが実際に格納するもの

PostgreSQL、MySQL、SQL Server、およびほとんどのデータベースエンジンでデフォルトのインデックスとして使われるのは、B-Tree(平衡木)です。インデックス対象の列の値をソート順で格納し、浅いページのツリーとして構成します。

  • 各リーフノードには、インデックスキーと、実際のテーブル行へのポインタが格納されます。
  • ツリーは常に平衡に保たれるため、テーブルのサイズにかかわらず、どの検索でも少数のページにアクセスするだけで済みます。

検索では、すべてのN行をスキャンする代わりに、ルートからリーフまでおよそlog(N)ステップでたどります。

最初のインデックスを作成する

CREATE INDEXを使ってB-Treeインデックスを作成します。レビュー担当者がテーブルと列をすぐに把握できるよう、分かりやすい名前を付けます。

このインデックスが存在すると、emailでフィルタリングするクエリは、フルスキャンではなく、数ページを読み取るだけで一致する行を見つけられます。

CREATE INDEX idx_users_email ON users (email);

-- Now this lookup uses the index instead of scanning
SELECT * FROM users WHERE email = 'ada@example.com';

B-Treeが高速化する操作

B-Treeは値をソートして保持するため、完全一致以外の操作も大幅に高速化します。面接官は、次の項目を正確に列挙できると高く評価します。

  • 等価検索:WHERE email = ?
  • 範囲検索:WHERE age > 30、BETWEEN、<、>=
  • プレフィックス一致:WHERE name LIKE 'Ada%'(ただし'%da'は不可)
  • インデックス対象列に対するORDER BY。ソートを回避できます
  • ソート構造の両端に位置するMIN/MAX

実例:範囲クエリ

数百万行のordersテーブルを考えてみます。あるレポート用クエリが最近の注文を要求しています。created_atにインデックスがある場合、エンジンはソート済みのインデックス内で範囲の開始位置まで移動し、必要なところまでだけ前方にたどります。

インデックスによって、フルテーブルスキャンが範囲を限定したスキャンに変わり、条件に一致する部分だけを読み取れるようになります。

CREATE INDEX idx_orders_created_at ON orders (created_at);

SELECT order_id, total
FROM orders
WHERE created_at >= '2026-01-01'
  AND created_at <  '2026-02-01';

インデックスはソートにも役立つ

見落とされがちな重要ポイントがあります。インデックスはすでにソート済みなので、エンジンはインデックス順に行を返し、別途ソートするステップを省略できます。これはORDER BYで重要であり、特に上位N件のページネーションで効果的です。

インデックスに一致する列でソートする場合、オプティマイザーはインデックスを順番に読み取り、十分な行数に達した時点で早期に停止できます。

-- Index on created_at lets this avoid a sort and stop after 10 rows
SELECT order_id, total
FROM orders
ORDER BY created_at DESC
LIMIT 10;

隠れたコスト:ヒープフェッチ

通常のB-Treeインデックスには、インデックス対象の列と行ポインタだけが格納されます。そのため、一致するエントリを見つけた後も、選択した他の列を読み取るためにテーブル(ヒープ)へ移動する必要があります。

この2回目のアクセスがヒープフェッチです。数行の場合は低コストですが、クエリが多くの行に一致すると高コストになります。これが、選択性の低いインデックスが無視されることがある理由の1つです。(後ほどカバリングインデックスでこの問題を解決する方法を学びます。)

インデックスが使われていることを確認する

インデックスが使われていると決めつけず、EXPLAINで証明してください。面接で実行計画を説明すれば、実際に理解していることを示せます。

  • Seq Scanは、インデックスが使われなかったことを意味します。
  • Index ScanまたはIndex Seekは、インデックスが使われたことを意味します。

インデックスを追加したのにシーケンシャルスキャンが表示される場合、プランナーはスキャンのほうが安いと判断しています。多くの場合、クエリがテーブルの大きな割合の行に一致していることが原因です。

EXPLAIN
SELECT * FROM users WHERE email = 'ada@example.com';
-- Look for: Index Scan using idx_users_email

主キーにはすでにインデックスがある

面接でよくある落とし穴です。PRIMARY KEYまたはUNIQUE制約を宣言すると、対応するB-Treeインデックスが自動的に作成されます。同じ列に2つ目のインデックスを追加する必要はなく、追加すべきでもありません。

そのため、主キーを使った結合や検索はすでに高速であり、「id列にインデックスを付けるべきですか」という質問は、たいてい引っかけです。すでに自動で処理されているからです。

-- This already builds a unique B-Tree index on (id)
CREATE TABLE users (
  id    BIGINT PRIMARY KEY,
  email TEXT UNIQUE
);

面接での伝え方

面接官がうなずきながら聞ける、簡潔な一文でまとめます。

「B-Treeインデックスはソートされた平衡構造であり、テーブル全体をスキャンする代わりに、log(N)回のページ読み取りでエンジンが行を見つけられるようにします。インデックス対象列に対する等価検索、範囲検索、プレフィックス検索、ORDER BYを高速化しますが、一致する各行について、インデックスに含まれない列を読み取るためのヒープフェッチが必要です。」

そして、EXPLAINで裏付けます。モデルと証拠を組み合わせることが、評価につながります。

理解度チェック

B-Treeインデックスが何を高速化するのか、メンタルモデルを確認してみましょう。

まとめ:B-Treeインデックス

次のレッスンに持っていく重要なポイントです。

  • B-Treeは、インデックス対象の値を平衡木にソートして格納し、log(N)の検索を実現します。
  • 等価検索、範囲検索、プレフィックス(先頭一致)LIKE、ORDER BY、MIN/MAXを高速化します。
  • インデックスに含まれない列については、一致する各行でヒープフェッチが必要です。
  • 列を関数でラップしたり、先頭にワイルドカードを付けたりすると、インデックスが無効になります。
  • 必ずEXPLAINで検証してください。PRIMARY KEYとUNIQUE制約ではインデックスが自動的に作成されます。

次は、1つのインデックスで複数の列をカバーする場合の列の順序について学びます。

よくある質問

「B-Treeインデックスとその効果」レッスンは無料ですか?

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

「B-Treeインデックスとその効果」で何を学びますか?

インデックスに実際に何が保存され、どの操作が高速化されるかを学びます。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「B-Treeインデックスとその効果」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. B-Treeインデックスとその効果
  2. 複合インデックスの列順
  3. カバリングインデックスとIndex-Only Scan
  4. インデックスが逆効果になる場合:書き込みと選択性
← SQL Interview Prepに戻る