1. インデックスの正体は「整理された辞書」
インデックスとは、本の後ろにある索引や辞書のように、データが特定の順番で並んでいる状態を指します。
データベースはこの「並び順」を利用して、「2023-10-01」というデータがどこにあるかを、二分探索などの効率的な方法で瞬時に見つけ出します。
2. なぜ「関数」を使うと遅いのか(イメージ図)
関数を使うということは、「辞書の中身をすべて書き換えてから探す」という作業をデータベースに強いることになります。
❌ 関数あり:TRUNC(created_at) の場合
データベースは、インデックス(索引)に書かれている元の値をそのまま使えなくなります。
| 元のデータ(索引) | TRUNC関数適用後(計算が必要) | 判定 |
| 2023-10-01 10:00 | → 2023-10-01 | 一致! |
| 2023-10-01 15:30 | → 2023-10-01 | 一致! |
| 2023-10-02 09:00 | → 2023-10-02 | 不一致 |
なぜ遅い?: 上の図のように、すべての行を一行ずつ取り出し、関数で計算し直してから比較しなければなりません。これをフルテーブルスキャン(全件走査)と呼びます。100万件あれば、100万回計算することになり、非常に時間がかかります。
3. なぜ「範囲指定」は速いのか
⭕ 範囲指定:created_at >= '2023-10-01' の場合
こちらは、インデックスの「並び順」をそのまま活用できます。
- インデックスの中から「2023-10-01 00:00:00」が始まる場所をピンポイントで探す(一瞬)。
- そこから「2023-10-02 00:00:00」の手前までを順番に読み取るだけ(非常に速い)。
| 処理ステップ | 動作イメージ |
| ステップ1 | 索引の「2023-10-01」のページをパッと開く |
| ステップ2 | 次の日のデータが出てくるまで、連続してデータを拾う |
| 結果 | 必要な行だけしか触らないので爆速 |
1. インデックスと関数の関係(なぜ使えないのか)
インデックスは、あらかじめ特定の列を「並び替えて保存したリスト」です。
例えば、created_at(登録日)にインデックスがある場合、DB内では以下のように整列しています。
| インデックス(整列済み) | ポインタ(実際のデータの場所) |
| 2023-10-01 10:00:00 | [データA] |
| 2023-10-01 15:00:00 | [データB] |
| 2023-10-02 09:00:00 | [データC] |
関数を使うとどうなるか?
WHERE TRUNC(created_at) = '2023-10-01' と書いた瞬間、DBはこう考えます。
「インデックスには『10:00:00』とか細かい時間が入っているな…。でもユーザーは『TRUNC(切り捨て)した後の値』で探せと言っている。インデックスの中身を全部計算し直さないと、どれが一致するか分からないぞ!」
結果として、DBはせっかく並び替えたインデックスを使わずに、テーブルの端から端まで全部チェック(フルスキャン)し始めてしまいます。



