プログラミング
Tin: Postgresのための全文検索
Tin: full-text search for Postgres (planetscale.com)
要約
PlanetScaleは、PostgreSQL向けの新しい全文検索拡張機能「TIN(Text INdex)」を発表しました。TINは、ブーリアン式、フレーズクエリ、あいまい検索、ワイルドカード、正規表現マッチング、ケース・アクセントの折り畳み、BM25スコアリングによるトップKクエリなどをサポートし、既存の拡張機能よりも高速で信頼性が高いとされています。
全文翻訳
Tin: Postgresのための全文検索
Tin: Postgresのための全文検索
Eric Ridge, Patrick Reynolds | 2026年9月16日
Postgresの機能で、私たちのお客様が最も多く求めているものの一つが全文検索です。本日、私たちはTINを発表できることを嬉しく思います。TINは、Postgresのための高速でフル機能、信頼性の高い全文検索拡張機能です。TINは「Text INdex」の略であり、それが機能することです。
TINは、すべてのPostgresおよびNekiデータベースでGAリリースとしてすぐに利用可能です。ぜひお試しください。
CREATE INDEX an_index_name ON table_name USING tin(text_column_name);
SELECT * FROM table_name WHERE text_column_name ==> 'some words';
私たちはTINを開発しました。なぜなら、優れたテキストインデックスは以下のすべてをサポートすべきだと信じているからです。
ブーリアン式、フレーズクエリ、スパンクエリ
あいまい検索、ワイルドカード、正規表現マッチング
大文字・小文字およびアクセントの折り畳み
COUNT(*)クエリとBM25スコア付きトップKクエリ
Postgresの優れたテキストインデックスは、これらすべての機能をサポートすると同時に、JOIN、全文検索と他のカラムタイプにまたがる複雑なWHERE句、継続的な更新、レプリケーション、バックアップ、および正しいトランザクション可視性を処理する必要があります。
Postgresには既に少なくとも3つの既存のテキスト検索インデックスがありますが、それらのいずれもこれらの要件をすべて満たしていませんでした。TINは満たします。TINはまた、驚くほど高速です。
TINは何のためのものか
アプリケーション開発者は、テキストインデックスを使用して様々な検索機能を構築します。Eコマースプラットフォームは、検索クエリに含まれるすべてのキーワードを含む上位10製品を検索する必要があるかもしれません。
SELECT * FROM products WHERE description ==> 'stretch denim jeans' ORDER BY tin.score(ctid) DESC LIMIT 10
訴訟証拠開示プラットフォームは、特定のキーワードの1つ以上を含むすべてのドキュメントを返す必要があるかもしれませんが、ランキングは一切気にしないかもしれません。
SELECT * FROM emails WHERE body ==> '[insider trading conspiracy]'
写真タグ付けプラットフォームは、特定のタグを持つ写真の正確な数を表示するかもしれません。
SELECT COUNT(*) FROM photos WHERE tags ==> '"san francisco"';
ほとんどのアプリケーションは、インデックスをクエリし続ける間、ドキュメントの挿入、更新、削除も必要とします。検索クエリは、コミットされた直後に新しい行または変更された行に基づいた一致を返す必要があります。
TINのパフォーマンスとベンチマーク
私たちは、上記のすべてのユースケースおよびそれ以上のユースケースのパフォーマンスを評価するためにベンチマークを実行しました。以下のワークロードを試しました。
結合(すべての単語を含む必要がある)、選択(いずれかの単語を含む必要がある)、およびフレーズ(単語を順番にすべて含む必要がある)クエリ、およびそれらすべてを組み合わせたもの。
ドキュメント数をカウントする、またはBM25スコアでトップKを要求するもの。
ベンチマーククエリワークロードと同時に、クライアントがインデックスに新しいデータを書き込んでいる場合とそうでない場合。
ワークロードとコーパス
私たちは、さまざまなテキストコーパスに対してTINのパフォーマンスを測定しました。Wikipedia全体、合計2.3TBのRedditコメントのコレクション、およびオープンアクセス研究論文、法律文書、パブリックドメイン書籍、Enronメールの797GBの混合ワークロードである「pile」です。この記事で共有するベンチマーク結果は、Stack Exchangeからの質問と回答のエクスポートに基づいています。これは1億5000万ドキュメントを含む85GBのコーパスです。コーパスには標準的なクエリトレースがないため、2〜15単語の範囲のサブ文字列をサンプリングすることによって合成的なトレースを生成しました。各サブ文字列を結合、選択、フレーズクエリの3つの方法で解釈しました。合計1,719クエリです。
テスト環境
私たちは、ローカルNVMeストレージと最新のAVX-512対応CPUを備えたAWS i7i.8xlarge EC2インスタンスでベンチマークを実行しました。各テキスト検索拡張機能について、Postgres 18.6を8 vCPUと32GBのRAMに制限された独立したコンテナにセットアップしました。これは、インデックスがPostgresバッファに収まらない場合に各インデックスシステムがどのようにパフォーマンスを発揮するかを示すのに十分小さいです。ベンチマークフェーズは順次実行されたため、エンジンはリソースを競合しませんでした。運用オーバーヘッドとレプリケーションの影響を最小限に抑え、競合するテキスト検索インデックスのベンチマークを再現したい人が誰でも同じインスタンスタイプとコンテナ制限を使用して実行できるように、スタンドアロンEC2インスタンスを選択しました。
Postgresコンテナに対して検索トラフィックを生成するために、ParadeDB Benchmarkerを使用しました。事前にウォームアップしてから測定を開始し、読み取られたバイト数とWALバイト書き込みのメトリックを追加するフォークバージョンがあります。Benchmarkerが提供するすべてのPostgresパラメータはデフォルトのままにしましたが、3つのパラメータを除きます。max_parallel_workersを8(40から)、shared_buffersを24GB(128MBから)、maintenance_work_memを24GB(64MBから)に設定し、コンテナのリソースに最適に合わせました。ターゲットPostgresサーバーと同じEC2インスタンスでBenchmarkerを実行し、ネットワーク遅延が測定に影響しないようにしました。
各シナリオについて、TIN v1.0.2のパフォーマンスを、ワークロードを完全に実行できる他のすべてのPostgresテキスト検索インデックス(ParadeDB v0.25.2、pg_textsearch v1.4.0、およびPostgres v18.6に組み込まれたGINインデックス)と比較して測定しました。TIN以外では、ParadeDBのみがすべてのベンチマークを完了できました。
インデックスのビルド時間とサイズ
インデックスはコーパスサイズの33%から61%を占め、準備、ビルド、完了に8分から129分かかりました。TIN以外の3つのエンジンは、コンテナに設定された32GBの制限で失敗したため、インデックスビルドのみ、表に示すように利用可能なRAMを増やしました。クエリを実行する前に、すべてのコンテナを32GBのRAMに戻しました。
|エンジン|合計時間|インデックスサイズ|必要RAM|
|---|---|---|---|
|TIN|8m10s|50.7 GB|32 GB|
|ParadeDB|19m20s|52.1 GB|64 GB|
|pg_textsearch|26m49s|41.5 GB|128 GB|
|Postgres GIN|2h09m04s|28.0 GB|64 GB|
混合クエリ、トップ10ランキング
最初のベンチマークでは、混合(結合、選択、フレーズ)クエリ、BM25スコアによるトップ10結果、インデックスへの同時書き込みなしのワークロードで、TINとParadeDBを比較します。TINはParadeDBの25倍のクエリ/秒を処理し、p99レイテンシは26倍低いです。GINは選択検索中にメモリ不足になるため、このベンチマークを完了できません。pg_textsearchは選択検索のみを処理するため、ベンチマークを完了できません。
結合およびフレーズクエリ、トップ10ランキング
次のベンチマークでは、同時書き込みなしのトップ10結合およびフレーズクエリのワークロードで、TIN、ParadeDB、Postgres GINを比較します。TINとParadeDBはBM25でランク付けし、GINはts_rank_cdでランク付けします。TINはParadeDBの10倍、GINの541倍のクエリを処理し、p99レイテンシはそれぞれ6倍、1,356倍低いです。pg_textsearchは、選択クエリのみを処理するため、ここでも除外されます。
同時書き込みによる選択クエリ
3番目の結果では、選択クエリ、BM25スコアによるトップ10結果、および毎秒1,000件のUPDATEクエリをターゲットとする同時クライアントを持つワークロードで、TIN、ParadeDB、pg_textsearchを比較します。TINはpg_textsearchの36倍、ParadeDBの57倍のクエリを処理し、p99レイテンシはそれぞれ24倍、36倍低いです。10分間の実行中、TINは270,279件の更新を完了しましたが、ParadeDBは185,584件、pg_textsearchはわずか735件でした。
ParadeDBの書き込み受付アプローチは、読み取りスループットとレイテンシを犠牲にします。pg_textsearchは、書き込みの有無にかかわらず同じ3.5 QPSのリーダーを維持します。これは、継続的な読み取りトラフィックにより書き込みトラフィックがロックを取得できず、書き込みが数秒後に停止するためです。GINは、選択クエリでメモリ不足になるため、ここでも除外されます。
インデックスがメモリに収まる場合
導入部で、TINは驚くほど高速であると主張しました。
最後のグラフは、インデックスが共有バッファに完全に収まる場合に、TIN、ParadeDB、およびPostgres GINが何ができるかを示しています。このワークロードは、Wikipedia(8.0GBのコーパス)に対する選択クエリでドキュメントをカウントします(ランク付けはしません)。pg_textsearchは、カウントクエリのみを実行でき、トップKクエリは実行できないため、ここにはありません。
完全な結果
おそらくグラフはこれで十分ですが、すべてのユースケースをカバーしているわけではありません。同じシナリオとさらにいくつかのシナリオを表形式で示します。「MB/query」列は、各インデックスがクエリごとにディスクまたはブロックキャッシュから読み取ったデータ量を示しています。TINの低い数値は