Prompt

DB内の文字列の検索に、生文字列での検索と正規表現での検索では、パフォーマンスにどれだけの差がある?

DB内での文字列検索において、「生文字列(完全一致・前方一致)」「正規表現」 のパフォーマンス差は、単なる処理速度の違いを超えて、「インデックスが使えるか否か」 という、情報工学における決定的な分断が存在するよ。

キミが追求する「一意な正しさ」と「効率」の観点から、この差を解剖してみよう。


1. インデックスの有無:勝負が決まる瞬間

パフォーマンスの差を分ける最大の要因は、CPUの計算力ではなく、B-Treeインデックス が機能するかどうかだ。

生文字列(特に前方一致)

  • 挙動: LIKE 'abc%' のような前方一致検索の場合、DBはB-Treeインデックスを使い、電話帳をめくるように高速に()目的のデータに辿り着ける。

  • 速度: 数百万件のデータがあっても、数ミリ秒で完了する。

正規表現

  • 挙動: REGEXP '^abc.*' は、一見前方一致と同じに見えるけれど、多くのDB(MySQLやPostgreSQLの標準設定)では正規表現に対してB-Treeインデックスを適用できない。

  • 速度: DBは 「フルテーブルスキャン」 (全件を一行ずつ読み込んで、正規表現エンジンにかける)を強制される。データ量に比例して時間()がかかるため、データが増えるほど絶望的な差が開くんだ。


2. エンジンの複雑性とCPU負荷

仮にインデックスを使わない条件(中間一致 LIKE '%abc%' vs REGEXP 'abc') で比較しても、正規表現は重い。

  • 生文字列検索: Boyer-Moore法 などの非常に高速な文字列マッチングアルゴリズムが使われる。これはCPUにとって非常に単純な比較作業だ。

  • 正規表現検索: NFA(非決定性有限オートマトン)DFA(決定性有限オートマトン) という複雑な状態遷移マシンをメモリ上に構築して実行する。

  • パフォーマンス差: インデックスなしの単純比較だけでも、正規表現は生文字列検索に比べて 数倍から数十倍 のCPUリソースを消費することが一般的だよ。


3. 実測値のイメージ(オーダーの違い)

データ量が100万件ある環境での、一般的なレスポンスタイムの目安はこんな感じだね。

検索手法インデックス利用実行時間の目安評価
完全一致 (=)有効1ms 未満最速。一意な定義に最適。
前方一致 (LIKE 'abc%')有効1~5ms実用的な高速検索。
中間一致 (LIKE '%abc%')無効100ms~データ量に応じてリニアに悪化。
正規表現 (REGEXP)ほぼ無効500ms~非常に重い。バックエンドの「穴」になりやすい。

見落とされがちな視点:ReDoS(正規表現の脆弱性)

正規表現を使う際、キミのような「スイスチーズモデル」を意識するエンジニアが最も警戒すべきは、ReDoS(Regular Expression Denial of Service) だ。

特定の「悪意ある正規表現」や「相性の悪い入力文字列」が組み合わさると、正規表現エンジンの計算量が指数関数的に爆発(バックトラッキングの嵐)し、DBサーバーのCPUを100%占有してシステムを落としてしまう。生文字列検索ではこの「一直線の穴」はほぼ起きないけれど、正規表現には常にこのリスクが付きまとうんだ。


解決策:どうしても「正規表現的に」高速検索したいなら

もしキミが「柔軟な検索」と「爆速」を両立させたいなら、DBの基本機能に頼るのをやめて、以下の 「[他の何か]」 を検討すべきだね。

  1. 全文検索エンジン (Elasticsearch / Meilisearch): データを N-gram や形態素解析で分解してインデックス化する。

  2. Trigramインデックス: PostgreSQL などで利用可能な、文字列を3文字ずつの断片にしてインデックスを貼る手法。これなら中間一致や一部の正規表現も高速化できる。


結論

  • 「一意なIDやコード」 を探すなら、絶対に 完全一致

  • 「サジェスト機能」 などを作るなら、 前方一致 LIKE

  • 正規表現 は、管理画面などの「少人数がたまに使う重い処理」に限定し、ユーザー向けの機能では 「全文検索エンジン」 という別の層を用意するのが、堅牢なアーキテクチャへの道だよ。

次は、「PostgreSQL で Trigram インデックスを使い、正規表現や中間一致を爆速にするための具体的な SQL と設定案」 について深掘りしてみる?

Would you like me to code a small benchmark script in Rust or Node.js to demonstrate the actual execution time difference between LIKE and REGEXP on a large dataset?