IDがアドレスではなく知識であるとき何が起こるか


アドレスは何も知らない

データベースで李舜臣を見つけるにはIDが必要だ。

Wikidataでは、李舜臣のIDは Q8492 である。

この数字は李舜臣を指す。 しかし文字列 Q8492 自体は何も知らない。

これが人なのか建物なのか知らない。 韓国人なのかフランス国民なのか知らない。 16世紀の人物なのか21世紀の人物なのか知らない。 生きているのか死んでいるのか知らない。

Q8492 はアドレスである。 郵便配達員は封筒の中に何が書かれているか全く知らない。 封筒のアドレスを見て配達するだけだ。

UUIDも同じである。550e8400-e29b-41d4-a716-446655440000。 128ビットの乱数。衝突を避けるためだけのユニーク性—— それが何を指すかについては何も教えてくれない。

過去50年間、データベースIDはこのように機能してきた。 IDはアドレスであり、何かを知るにはそのアドレスをたどってデータを読まなければならない。


たどらなければわからない

なぜこれが問題なのか。

「19世紀生まれのドイツ人男性哲学者」を見つけたいとしよう。

従来のデータベースでは、こうなる:

1. personsテーブルで gender = 'male' をフィルタ
2. nationalitiesテーブルとJOINし country = 'Germany' をフィルタ
3. birth_datesテーブルとJOINし year BETWEEN 1800 AND 1899 をフィルタ
4. occupationsテーブルとJOINし occupation = 'philosopher' をフィルタ

4回のJOIN操作。 各JOINは2つのテーブルの行を比較する。 テーブルが大きければインデックスを走査し、インデックスがなければフルスキャンを実行する。 10億レコードの場合、このプロセスは数秒から数十秒かかる。

なぜこんなに複雑なのか。

IDが何も知らないからだ。 Q8492 を見ても、これがドイツ人か韓国人か判断できないから、 別のテーブルに行ってその情報を取得しなければならない。

あらゆる質問に対して、IDが指す先をたどらなければならない。 これがデータベースが50年間払い続けてきたコストである。


もしID自体が知っていたら?

前提を逆転させよう。

もしID自体が本質的な情報を含んでいたら?

IDを見るだけで、 それが人間を指すのか、どの国の出身か、 どの時代に属するか、どう分類されるかがわかったら?

「19世紀ドイツ人男性哲学者」を見つけるのに、 JOINは不要になる。

10億のIDをスキャンして、 ビットを調べるだけで各IDがマッチするか即座に判断できる。

これが意味整列インデックスの核心的アイデアである。


意味をIDに整列させる

SIDX(意味整列インデックス)は64ビットの識別子である。

この64ビットは乱数ではない。 各ビットの位置に意味が割り当てられている。

上位ビットに最も重要な情報がある。 これはどんな種類のエンティティか?人、場所、イベント、概念?

次のビットには分類情報がある。 人であれば、どの時代?どの地域?

下位ビットにはますます具体的な情報が入る。

鍵となる原則はこうだ:

ビットの順序が情報の重要度の順序である。

最も基本的な分類が最上位に、 最も細かい区分が最下位に。

これは単なるソートではない。 これは設計哲学である。


10億から1万へ、ワンパスで

SIDXの実用的な威力は数字に表れる。

WMSは10億のエンティティを保持している。 各エンティティのSIDXは64ビット。 合計サイズ:10億 x 8バイト = 8 GB。

この8 GBは完全にメモリに収まる。

「人間でありかつ東アジア出身のエンティティ」を見つけたいとしよう。 上位ビットに「人間」フラグと「東アジア」コードが含まれているため、 単一のビットマスクでフィルタリングできる。

mask   = 0xFF00_0000_0000_0000  (上位8ビット:タイプ + 地域)
target = 0x8100_0000_0000_0000  (人間 + 東アジア)

for each sidx in 1_billion:
    if (sidx & mask) == target:
        add to candidates

この操作はSIMDで並列化される。 AVX-512を使えば、一命令で8つのSIDXを同時に比較できる。 10億エントリのスキャン:約12ミリ秒。

GPUなら?1ミリ秒未満。

10億レコードが1万に絞られる。 残り1万の詳細フィルタリングは一瞬で終わる。

ゼロJOIN。 ゼロインデックスツリー走査。 ビット単位ANDが一回だけ。


なぜ64ビットで十分なのか

最初は、より大きな空間が必要だと思っていた。

32バイト(256ビット)。32次元のFP16ベクトル。 エンティティのあらゆる主要属性をIDに詰め込もうとした。 人間かどうか、性別、国籍、時代、職業、地域、生存状態、分類パス…

しかし気づいた。

IDはすべてを知る必要がない。

10億レコードを1万に絞るだけでよい。 残りはWMSが処理する。

チェックポイントだと考えればよい。 高速道路の料金所で、 ナンバープレートから「この車は京畿道方面に向かっている」と判断するのに、 トランクに何が積まれているかを知る必要はない。

64ビットで十分だ。 上位ビットでタイプと大まかな分類を捉え、 下位ビットでより細かい分類を行う。 10億レコードを1万に絞るには64ビットで十分以上だ。

そして64ビット = 4つの16ビットワード。 ストリーム内で自然に流れる。 32バイトのIDはストリームを重くするが、 64ビットSIDXは軽くて速い。


グレースフルデグラデーション:ビットが切り詰められても意味は生き残る

意味整列のもう一つの強みはそのデグラデーション特性である。

SIDXのビットは重要度の高い順に並んでいるため、 下位ビットが損傷したり切り詰められたりしても、 上位ビットの核心情報は保存される。

完全な64ビット:  "李舜臣、16世紀朝鮮の海軍将領"
48ビット:       "16世紀朝鮮の軍人"
32ビット:       "16世紀東アジアの人間"
16ビット:       "人間"
8ビット:        "物理的エンティティ"

情報が切り詰められるにつれ具体性は失われるが、 最も基本的な分類は最後まで残る。

これは「グレースフルデグラデーション」原則のビットレベルの実装である。

ネットワークの中断で部分的なデータしか届かなくても、 システムは「正確に誰かはわからないが、少なくとも人間についての話だ」とわかり、 推論を続けることができる。

ぼやけた輪郭は完全な沈黙よりましだ。 部分的な理解は完全な失敗よりましだ。


クエリがIDになる

意味整列インデックスが開く最も興味深い可能性は、 自然言語クエリを一時的なSIDXに変換できることだ。

ユーザーが尋ねる:「壬辰戦争で日本海軍を破った将軍は誰?」

エンコーダがこの質問を分析する。 人間。東アジア。16世紀。軍事関連。 これらの属性をビットに組み立てると、一時的なSIDXが生成される。

この一時的なSIDXがWMS内の10億のSIDXをスキャンする。 ビットパターンが最も類似するエンティティが候補として浮上する。 李舜臣、元均、権慄、李億祺…

候補の詳細情報を照合して最終回答を得る。

これは検索とエンティティリンキングを単一のメカニズムに統合する。 別の検索エンジンは不要。 別のNER(固有表現認識)パイプラインも不要。 一回のSIDX比較だけで済む。


なぜBツリーではないのか?

従来のデータベースはBツリーインデックスを使用する。

Bツリーはソートされたデータ中の特定値をO(log n)で見つけることに優れている。 「Q8492を見つける」には最適だ。

しかし「人間でありかつ東アジア出身のすべてのエンティティを見つける」には弱い。 複合条件検索は複数のインデックスの交差を必要とし、 交差のコストはデータ規模とともに急激に増大する。

SIDX + SIMD全数スキャンは根本的に異なるアプローチを取る。

Bツリーが「このアドレスに誰が住んでいるか」に素早く答える電話帳だとすれば、 SIDXスキャンは「この特徴を持つのは誰か」に素早く答えるプロファイリングだ。

質問の性質が異なり、最適なデータ構造も異なる。

クエリタイプBツリーSIDXスキャン
特定IDでの検索O(log n)、最適不要(ハッシュを使用)
複合条件フィルタリングJOINが必要、遅いビット単位AND一回、高速
類似エンティティ検索不可能ベクトル類似度で可能
挿入O(log n)、再バランスO(1)、追記
実装複雑度高い低い

WMSはBツリーを使わない。 10億のSIDXをメモリにロードし、 SIMDビットマスクで全数スキャンを行う。

シンプル。総当たり。高速。


ハフマンの知恵

SIDXのビット割り当て構造はハフマン符号化の原則に従っている。

ハフマン符号化では、頻出するシンボルに短いコードが割り当てられ、 まれなシンボルに長いコードが割り当てられる。

SIDXでは、最も頻繁に必要とされる分類情報が上位ビットを占め、 まれにしか必要とされない詳細が下位ビットを占める。

同じ原則がこの言語のパケットタイププレフィックスを支配している。 最高頻度のTiny Verb Edgeが最短のプレフィックスを得る。 低頻度のEvent6 Edgeが長いプレフィックスを得る。

ハフマンの知恵がこの設計のあらゆる層を貫いている。 一ビットたりとも無駄にされない。 最も重要なものに最も低いコスト。


まとめ

従来のIDはアドレスである。アドレスは何も知らない。

  1. IDが意味を持たなければ、毎回データのところまでたどらなければならない。それがJOINだ。
  2. 10億レコードに対する4回のJOINは遅い。
  3. SIDXは意味整列によって意味を直接IDに符号化する。
  4. ビットマスクAND一回で10億レコードが1万に絞られる。ゼロJOIN。
  5. 64ビットで十分。IDはすべてを知る必要はない——候補を絞るだけでよい。
  6. 最も重要な情報が上位ビットを占めるため、ビットが切り詰められても核心的意味は残る。
  7. 自然言語クエリを一時的なSIDXに変換すれば、検索がベクトル演算になる。

IDがアドレスであることをやめ知識になった瞬間、 データベースのルールが変わる。