応用情報技術者 2017年 春期 午前2 問28
問題文
“部品” 表のメーカコード列に対し、B+木インデックスを作成した。これによって、“部品”表の検索の性能改善が最も期待できる操作はどれか。ここで、部品及びメーカのデータ件数は十分に多く、“部品” 表に存在するメーカコード列の値の種類は十分な数があり、かつ、均一に分散しているものとする。また、“部品” 表のごく少数の行には、メーカコード列に NULLが設定されている。実線の下線は主キーを、破線の下線は外部キーを表す。
部品(部品コード, 部品名, メーカコード)
メーカ(メーカコード, メーカ名, 住所)
選択肢
ア:メーカコードの値が1001以外の部品を検索する。
イ:メーカコードの値が1001でも4001でもない部品を検索する。
ウ:メーカコードの値が4001以上、4003以下の部品を検索する。(正解)
エ:メーカコードの値がNULL以外の部品を検索する。
🔒 解説は解答すると表示されます
B+木インデックスの範囲走査【午前2解説】
正解の理由
B+木インデックスは葉ノードが順に連結されているため、連続するキー範囲(例:4001以上4003以下)を効率的に範囲走査できます。問題文の条件(メーカコードの値の種類が多く均一に分散)において、特定の連続範囲を指定する検索はインデックスを用いたリーフの順次読み取りで済み、ディスクI/Oや比較回数が小さくなります。したがって、ウの「メーカコードが4001以上4003以下の部品を検索する」操作で最も性能改善が期待できます。
解法ステップ
- B+木インデックスの性質を確認する:葉ノードは順次連結され、等価検索と連続範囲検索(区間検索)を高速に処理できる。
- 各選択肢のクエリを「連続レンジか」「除外か」「多くの行にヒットするか」で分類する。
- 高選択性(対象行が少ない)かつ連続した範囲であればインデックスが有効、除外条件や広範囲・高ヒット率ならインデックス効果が薄いと判断する。
- 問題の前提(値が多数かつ均等分布、NULLはごく少数)を踏まえ、最も効率的なのは連続範囲検索であると結論付ける。
選択肢別の誤答解説
- ア: メーカコードが1001以外の部品を検索する。
「1001以外」は除外条件であり、B+木では理論上は「<1001」と「>1001」の2つの連続範囲の走査に分かれます。つまり2つの範囲走査を行う必要があり、除外対象が単一値でも結果はほとんど全表を対象にする可能性が高い(選択性が低い)ため効率は悪くなりがちです。従ってウに比べて性能改善効果は小さいです。 - イ: メーカコードが1001でも4001でもない部品を検索する。
これはさらに「特定の値を除く」条件で、実際にはほぼ全行が対象になる(全体から極めて少数を除く)ため、インデックスを使っても多数のエントリ走査が必要になり効率が悪い。除外値が少数ならなおさらインデックスでの利益は乏しいです。 - ウ: メーカコードが4001以上、4003以下の部品を検索する。
連続した小さな区間を指定しており、B+木の葉ノード連結を活かせる典型的な範囲検索です。連続範囲なので最初のキー位置まで移動してから隣接リーフを順次読めば良く、ディスクアクセスが少なくて済みます(このため最も効果が高い)。 - エ: メーカコードがNULL以外の部品を検索する。
「IS NOT NULL」は対象行が大多数になる可能性が高く、インデックスを使ってもほぼ全行を走査する結果となります。またデータベースによってはNULL値をインデックスに含めない場合があり、その場合はインデックスでNULL以外を取り出す方法が制限されることもあります。いずれにせよ選択性が低い検索です。
よくある誤解
- 「除外条件はインデックスでは一切使えない」
誤りです。B+木は両側の範囲(例:<1001 と >1001)を個別に範囲走査できますが、除外条件は通常2つ以上の非連続範囲に分かれるため、範囲走査が複数回必要になり効率が落ちやすい点が問題です。 - 「インデックスがあれば常に高速」
インデックス効率は選択性(対象行割合)やアクセスパターンに依存します。ヒット行が表全体の大半を占める場合、フルスキャンの方が高速になることもあります。 - 「NULLは必ずインデックスに含まれる」
DBMSによって異なります。NULLを索引に含めない実装があり、その場合は IS NOT NULL の処理が特殊になります。
補足コラム
B+木インデックスのレンジ検索コストはおおむね「初期位置の探索コスト(木高さ分のIO)」+「範囲内の葉ページ走査コスト」です。値の種類が多く均一に分散しているとき、等価検索で得られる平均ヒット行数は次のように見積もれます:
件の行、値の種類が 種類なら等価検索の期待ヒット数は約 。
範囲検索では範囲幅に応じて該当するキー数が増え、走査する葉ページ数は比例します。したがって「狭い連続レンジ」は最も恩恵が大きい典型ケースです。
範囲検索では範囲幅に応じて該当するキー数が増え、走査する葉ページ数は比例します。したがって「狭い連続レンジ」は最も恩恵が大きい典型ケースです。
SQL例(イメージ):
-- ウ:範囲検索(インデックスが有効)
SELECT * FROM 部品 WHERE メーカコード BETWEEN 4001 AND 4003;
-- ア:除外(2つの範囲走査)
SELECT * FROM 部品 WHERE メーカコード <> 1001;
-- エ:IS NOT NULL(選択性次第)
SELECT * FROM 部品 WHERE メーカコード IS NOT NULL;
FAQ
Q1: 「!=」や「<>」はインデックスを使えますか?
A1: DBMSにより実行計画は異なりますが、一般には「!=」は連続範囲の組合せ(2つ以上)として処理されるため、インデックスを利用できても複数範囲の走査や大規模なスキャンになりやすく効率が落ちます。
A1: DBMSにより実行計画は異なりますが、一般には「!=」は連続範囲の組合せ(2つ以上)として処理されるため、インデックスを利用できても複数範囲の走査や大規模なスキャンになりやすく効率が落ちます。
Q2: IS NOT NULL はインデックスの恩恵を受けますか?
A2: 候補行がごく少数なら恩恵がありますが、ほとんどの行が非NULLであればインデックスを使っても多くの読み取りが必要になり効果は小さいです。加えて、DBMSによってはNULLをインデックスに含めない実装があるため挙動に注意が必要です。
A2: 候補行がごく少数なら恩恵がありますが、ほとんどの行が非NULLであればインデックスを使っても多くの読み取りが必要になり効果は小さいです。加えて、DBMSによってはNULLをインデックスに含めない実装があるため挙動に注意が必要です。
Q3: 複数列インデックスと範囲検索の相性は?
A3: 複合インデックスでは左側のキーから順に利用されます。範囲条件が左側の列にかかると、右側の列の条件は通常インデックスの全域走査になりやすいので設計に注意が必要です。
A3: 複合インデックスでは左側のキーから順に利用されます。範囲条件が左側の列にかかると、右側の列の条件は通常インデックスの全域走査になりやすいので設計に注意が必要です。
関連キーワード: B+木、範囲走査、選択性、NULLインデックス、範囲検索、不等号検索

\ せっかくなら /
応用情報技術者を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

