中級では「巡回(HTTP)→ 切り出し(形態素解析)→ 転置(索引)→ 採点(関連度+リンク評価)」という分業を追いました。上級では、その各部品の内部構造とスコアの計算、そして大規模化まで踏み込みます。
概要 — まず全体をつかむ
アニメーション『検索の前準備と本番』を開く
- 世界中のWebサイト — 何十億ページもある本棚。検索エンジンの外にある
- クローラ — リンクをたどってページを読んで回る自動の巡回ロボット
- 索引(インデックス) — 「この言葉はこのページにある」をまとめた巨大な逆引き帳
- あなた — 検索窓に言葉を打つ人
詳細 — 1段階ずつ追う
クローリングとインデックス構築
クローラの正体は超大規模なHTTPクライアントでした。上級では「どう賢く回り、どう索引へ落とすか」を見ます。
- フロンティア ※1 — 未訪問URLの巨大な待ち行列。ただ古い順ではなく、更新頻度や重要度で優先度を付けて取り出す
- 重複除去 — URLを正規化し、本文のハッシュで同一コンテンツを弾く。ミラーやパラメータ違いの重複に持ち時間を奪われないため
- 差分クロール — 変わっていないページは再取得を控え、変化しやすいページを厚く回る
- レンダリング待ち — JSで中身を組み立てるページは、ブラウザ 相当の実行工程が要る。素のHTML取得より桁違いに重いので別枠の順番待ちになる
集めた文書は、バッチと増分で索引に落とします。大量の文書からセグメント(部分索引)を作り、それらをマージして大きな索引へ育てる、という積み上げ方が定番です。
登場人物メモ(※の説明):
- ※1 フロンティア — これから訪問するURLの管理キュー。優先度付けが「クロールバジェット」の使い方を決める
やさしく言うと(中級)
🎬 アニメーション『検索の前準備と本番』の ①〜② のところです!
クローラの実体は、超大規模なHTTPクライアントです:
- URLの一覧(フロンティア)から次の訪問先を取り出し、HTTPのGETでページを取得する——『パケットの旅』とまったく同じ手順を毎秒数百万回やっている
- 取得したHTMLからリンクを抽出して、一覧に追加する
- 訪問前にrobots.txt※1 を確認し、「入らないで」と書かれた場所は避ける
- サイト側はサイトマップ※2 で「ここにページがあります」と案内できる
- JSで中身を組み立てるページは、後段のレンダリング工程※3 の順番待ちになる
登場人物メモ(※の説明):
- ※1 robots.txt — サイトの入り口に置く「クローラへのお願い」ファイル。強制力はない紳士協定
- ※2 サイトマップ — サイト側が提出するページ一覧。リンクの少ない新ページを見つけてもらう近道
- ※3 レンダリング工程 — クローラ側でJSを実行してページを完成させる処理。素のHTML取得より桁違いに高コストなので、別枠の順番待ちになる
⚠️ イレギュラー(クロールの落とし穴):
- robots.txt を守りにしてしまう — 見られて困るページは認証で守る。robots.txt は「行儀のよい相手へのお願い」でしかない
- 無限に生成されるURL — カレンダーの「次の月」リンク等でURLが無限に湧くと、クローラの持ち時間(クロールバジェット)を浪費して肝心のページが読まれない
転置インデックスの中身
中級で「単語→文書ID一覧」と紹介した索引を、もう一段開けます。単語ごとに紐づく文書の並びを ポスティングリスト ※1 と呼びます。
- ポスティングの中身 — 文書IDだけでなく、出現回数(後の採点用)と出現位置(フレーズ検索用)を添える
- 前処理の三点 — トークナイズ ※2(語に切る)→ 正規化(大文字小文字・全角半角・表記揺れを揃える)→ ステミング ※3(活用や語尾を語幹に寄せる)
- 辞書と圧縮 — 語→ポスティングの先頭を引く辞書を別に持ち、文書IDは差分(ギャップ)符号化などで圧縮して巨大化を抑える
登場人物メモ(※の説明):
- ※1 ポスティングリスト — ある単語を含む文書の並び。転置インデックスの本体
- ※2 トークナイズ — 本文を索引の単位(トークン)に切り分ける処理。日本語では形態素解析がこれを担う
- ※3 ステミング — 「走る/走った/走れば」を同じ語幹に寄せる正規化。英語の running→run のような揺れの吸収
やさしく言うと(中級)
🎬 アニメーション『検索の前準備と本番』の ③ のところです!
「逆引き帳」の正式名は転置インデックス※1 です。作る手順:
- ページ本文から単語を切り出す——日本語は空白で区切られていないので、形態素解析※2 で「カレー / の / 作り方」と分割する
- 表記を正規化する(大文字小文字・全角半角・「作り方/つくりかた」などの揺れの吸収)
- 「単語 → その単語を含む文書IDの一覧」の向きで表に積む。位置情報も添える(後でフレーズ検索や近接度に使う)
向きがすべてです。「文書→単語」の順だと検索のたびに全文書をめくることになる。「単語→文書」に転置してあるから、何十億ページでも一撃で引けます。
登場人物メモ(※の説明):
- ※1 転置インデックス — 本の巻末索引と同じ向きのデータ構造。検索エンジンの心臓部
- ※2 形態素解析 — 文を最小の意味単位に切り分ける処理。日本語検索には必須の前処理
⚠️ イレギュラー(索引の宿命):
- 索引は常に少し古い — ページを更新しても、再クロール・再索引までは古い内容で検索される
- 切り出しの失敗 — 新語や固有名詞は辞書にないと変な位置で切られ、検索に引っかからないことがある
ランキング — TF-IDFからBM25へ
絞り込んだ候補に順位を付ける採点を、古典から見ます。
- TF-IDFの発想 — その文書に多く出る語(TF)ほど効き、世間では珍しい語(IDF)ほど効く、という重み付け。中級で触れた「関連度」の土台
- BM25 — TF-IDFの弱点を補う定番。出現回数の効果を飽和させ(同じ語を1万回書いても青天井にはならない)、文書長で正規化する(長い文書がただ有利になるのを防ぐ)
- 学習型ランキング — 現代の検索は、これら多数の特徴量を機械学習モデルで合成し、クリック傾向なども取り込んで並べる
素朴なTFの弱点(詰め込みが有利)を、BM25の飽和と正規化がどう塞ぐか——ここが古典的採点の要点です。
やさしく言うと(中級)
🎬 アニメーション『検索の前準備と本番』の ④〜⑦ のところです!
0.5秒の本番でやっているのは「絞り込み」と「採点」です:
- 検索語を同じ手順(形態素解析・正規化)で単語に分ける
- 各単語の文書一覧を索引から引き、共通部分に絞り込む
- 絞った候補を採点する。代表的な観点が2つ——関連度※1(その単語がその文書でどれだけ「効いて」いるか)と、PageRank※2(どれだけ信頼あるページからリンクされているか)
- 実際は数百の要素(新しさ、モバイル対応、検索者の言語・地域…)を合成した総合点で並べる
⚠️ イレギュラー(採点をめぐる攻防):
- SEOスパム — 単語の詰め込み、リンクの売買など、採点の癖を突く手口。採点式の非公開・随時更新はこのいたちごっこの防御側
- 順位は人によって違う — 言語・地域・履歴で採点が変わるので、「自分のPCでは1位」は他人の1位を意味しない
登場人物メモ(※の説明):
- ※1 関連度(TF-IDFの発想) — 「その文書に多く登場し、かつ世間では珍しい単語」ほど効く、という重み付けの古典。現在は機械学習モデルに発展している
- ※2 PageRank — リンクを「他者からの推薦」とみなす採点。詰め込みスパムへの対抗として検索の歴史を変えた発想
検索エンジンに「載せてもらう」側の視点 — SEOの正体
このユニットを裏返すと、SEO(検索エンジン最適化)の正攻法がそのまま出てきます: クローラが辿れるようにリンクとサイトマップを整える(①)/ 単語が正しく切り出せる自然な文章を書く(②)/ 検索者の意図に応えて他者からリンクされる内容にする(③)。「裏技」に見えるSEOの実体は、この3工程への適合です。採点の癖を突く裏技側はスパムとして対策され続けます。
まとめ——検索が一瞬なのは、巡回(HTTP)→ 切り出し(形態素解析)→ 転置(索引)→ 採点(関連度+リンク評価)という分業の賜物です。「検索に出ない」ときは、この順に「クロールされているか→索引に載ったか→採点で沈んでいるか」と切り分けていきます。
クエリ処理(AND・OR・フレーズ)
複数語のクエリは、ポスティングリストの集合演算として処理されます。
- AND — 各語のポスティングリストの積(共通する文書ID)を取る
- OR — 和を取る
- フレーズ検索 — 語が索引に持つ出現位置を使い、「隣り合っているか」を確かめる。位置がなければ「順不同で両方含む」までしか言えない
- 高速化 — ソート済みリストを飛ばし読みするスキップリストや、上位k件だけ確定できれば全走査を打ち切る枝刈りで、巨大なリストの積和を速く済ませる
リンク解析(PageRank)
Web検索特有の採点が、リンク構造の解析です。
- リンク=推薦 — 信頼あるページから多くリンクされるページは、それ自体も信頼できるとみなす
- 反復計算 — 全ページの評価を、リンクをたどって少しずつ配り合い、値が落ち着くまで繰り返して求める(ランダムに links をたどり歩く閲覧者のモデル)
- スパム耐性 — 語の詰め込みだけでは上がらない軸を足すことで、本文操作だけのスパムに強くなった。もっとも、リンク売買という新たないたちごっこも生んだ
本文の関連度(BM25など)と、この外部からの評価を合成するのが、Web検索のランキングの骨格です。
大規模化 — シャーディングと分散
何十億という文書は、1台の索引には収まりません。分割して並列に引くのが基本です。
- シャーディング — 文書集合を複数のシャードに分け、各シャードが自分の担当分の完全な転置インデックスを持つ
- 分散クエリ — 検索語を全シャードへ同時に投げ、各シャードで上位k件を出し、集約役がそれらをマージして最終順位を作る
- レプリカ — 各シャードを複製して、故障への冗長性と読み取りスループットを稼ぐ
- キャッシュ — よく出る検索結果や、頻出語のポスティングリストを キャッシュ して往復を減らす
B木索引との違い
同じ「索引」でも、DBの B木索引 と全文検索の転置インデックスは狙いが違います。
アニメーション『インデックスと全表走査』を開く
- B木索引 — 列の値をソートして並べる構造。等値・前方一致・範囲(
WHERE age > 30やLIKE 'ab%')に強い。ただし本文の途中に出る語では引けない - 転置インデックス — 本文を語に割り、語の側から文書を引く。だから「文章中のどこかにこの語がある文書」を全文から即座に集められる
DBで LIKE '%語%' が遅い(索引が効かず全表走査になりがち)のに対し、全文検索がそれを一撃で返せるのは、この索引の向きの違いが理由です。用途に応じて、両者は使い分けられます。
関連する知識
理解度チェック
そのまま解けます(成績は保存されません)。無料アカウントを作ると、学習の記録と進捗の山登りが始まります。
問1. 全文検索の転置インデックスが DBのB木索引と根本的に異なる点はどれ?
問2. ランキングでBM25がTF-IDFに加えた主な改良はどれ?
問3. 複数語のANDクエリを転置インデックスで処理するとき 何を計算する?
問4. フレーズ検索で「語が隣り合っているか」を確かめられるのは ポスティングに何を持たせているから?
問5. 何十億もの文書を複数のシャードに分けるとき 各シャードが持つのはどれ?
問6. 「running を run に寄せる」ように 活用や語尾を語幹に揃える正規化を何と呼ぶ?
問7. ある単語を含む文書の並び(文書ID・出現回数・出現位置を持つ)を 転置インデックスでは何と呼ぶ?(カタカナ)
問8. クローラがこれから訪問する未訪問URLを管理する巨大な待ち行列を何と呼ぶ?(カタカナ)