- Tantivy は Rust で書かれた高速なフルテキスト検索エンジンライブラリであり、完成された検索サーバーではなく、検索エンジンを作る際に使う crate に近い
- 設計は Apache Lucene から強い影響を受けており、Elasticsearch や Apache Solr の代替サーバーを探している場合は、Tantivy 上に構築された分散検索エンジン Quickwit を確認するよう案内している
- 機能には、フルテキスト検索、BM25 スコアリング、自然言語クエリ、フレーズ検索、増分インデキシング、マルチスレッドインデキシング、mmap ディレクトリ、SIMD 整数圧縮、ファセット検索、JSON フィールド、集計 Collector などが含まれる
- stable Rust で動作し、Linux、macOS、Windows をサポートし、起動時間が 10ms 未満 のためコマンドラインツールに適しているとしている
- 分散検索は Tantivy の対象外であり、ドキュメントの変更は既存ドキュメントを削除して再インデックスする必要があり、新しいドキュメントは
commit 後に IndexReader の再読み込みと新しい Searcher の取得を経て検索可能になる
Tantivyの位置づけと設計
- Tantivy は Rust で書かれた高速なフルテキスト検索エンジンライブラリ
- Elasticsearch や Apache Solr のようにそのまま実行する検索エンジンサーバーではなく、そのような検索エンジンを作る際に利用できる crate
- 設計面では Apache Lucene により近く、Lucene の設計から強い影響を受けている
- Elasticsearch や Apache Solr の代替を探している場合は、Tantivy 上に構築された分散検索エンジン Quickwit を確認するよう案内している
性能とベンチマーク
- Tantivy はクエリとコレクション種別ごとの性能を分けた benchmark を提供している
- ベンチマーク結果はクエリの性質や負荷によって変わる可能性がある
- ベンチマークの詳細は search-benchmark-game リポジトリで確認できる
- FAQ によると、検索レイテンシのベンチマークでは Tantivy は Lucene より平均で約 2倍高速
検索・インデキシング機能
-
検索機能
- フルテキスト検索
- Lucene と同様の BM25 スコアリング
- 自然言語クエリ対応:
(michael AND jackson) OR "king of pop"
- フレーズ検索対応:
"michael jackson"
- 範囲クエリ
- ファセット検索
- JSON Field
- Aggregation Collector: histogram, range buckets, average, stats metrics
-
インデキシング機能
- 増分インデキシング対応
- マルチスレッドインデキシング対応
- 英語版 Wikipedia のインデックス作成はデスクトップで 3 分未満で完了するとしている
- 選択的な term frequency と position indexing によるインデキシング設定が可能
- deletes 付き LogMergePolicy をサポート
- Searcher Warmer API を提供
-
ストレージとフィールド
- mmap directory をサポート
- u64、i64、f64 の single-valued および multivalued fast fields をサポート
&[u8] fast fields をサポート
- text、i64、u64、f64、dates、ip、bool、hierarchical facet fields をサポート
- ドキュメントストア圧縮は LZ4、Zstd、None をサポート
トークナイザーと言語対応
- トークナイザーは設定可能で、17 のラテン語系言語について stemming を利用できる
- サードパーティ製トークナイザーのサポートも提供している
- Tantivy 用トークナイザーを実装する際は
tantivy-tokenizer-api crate に依存する必要がある
実行環境と始め方
- Tantivy は stable Rust で動作する
- 対応 OS は Linux、macOS、Windows
- 起動時間が 10ms 未満 のためコマンドラインツールに適している
- 開始資料
- ローカルビルドとテストは次のコマンドで行う
git clone https://github.com/quickwit-oss/tantivy.git
cd tantivy
cargo test
対象外の機能とデータ変更モデル
- 分散検索 は Tantivy の対象外
- 分散検索が必要なら Quickwit を確認するよう案内している
- Tantivy のデータは immutable
- ドキュメントを変更するには既存ドキュメントを削除して再インデックスする必要がある
- インデキシング中のドキュメントは
IndexWriter で commit が呼ばれた後に検索可能になる
- 既存の
IndexReader は変更を反映するために再読み込みが必要
- 変更は新たに取得した
Searcher でのみ見える
バインディングと利用例
- 他言語から利用できるバインディング
- Tantivy の利用例
- seshat: Matrix メッセージデータベース/インデクサー
- tantiny: Ruby 向けの小規模フルテキスト検索
- lnx: REST API を備えた適応型の typo 許容検索エンジン
- Bichon: WebUI を備えた軽量・高性能な Rust メールアーカイバー
- Tantivy を利用している企業として Etsy、ParadeDB、Nuclia、Humanfirst.ai、Element.io が挙げられている
1件のコメント
Hacker Newsの意見
このライブラリを作った人たちは本当にすごい。昨年、長らく放置していた古いPython 2 AppEngineのコードベースを置き換える際に、https://progscrape.com [1]をこれの上に作り直したのだが、素晴らしいライブラリで、ものすごく速い。
Raspberry Pi上で100万件のストーリー全体を数秒でインデックスできるほど。
自宅のPiで全文検索サービスを動かしていて、ピーク負荷は数rps程度なので大きくはないが、CPUも数%以上にほとんど跳ね上がらない。Pi上で検索を約100rpsまで負荷テストしたが、持ちこたえた。ほぼそのまま組み込める非常に有用なライブラリで、バグ報告にもチームが非常に素早く対応してくれ、バグもごく少なかった。
こうした小さなデバイスで検索の応答性がどんなものかを見るには、各ストーリーのラベルを押してみればよい。事実上即座にクエリされ、最大で10年 × 12か月分の検索シャードに当たっている: https://progscrape.com/?search=javascript
現代的なプロジェクトなら、Luceneよりもこれを見てみることを勧める。小さなARM64でもこれだけうまくスケールするので、より大きなサーバーでははるかに良い体験になる可能性が高い。
[1] https://github.com/progscrape/progscrape
ユーザーがバックアップを検索できるようにしたかったし、Rustを使っているのでTantivyがぴったりに見えた。メール1通をインデックスする速度がとても速く、別スレッドに移す必要すらなく、数千通のメール検索も問題なさそう。
Rustアプリケーションに検索が必要なら、Tantivyを見てみるとよい。
Error: PersistError(UnexpectedError("Storage fetch panicked"))が表示される。基本的に必要なのは全文検索だけ。
最近ParadeDBの中でTantivyを見つけた。ParadeDBはElasticの代替を目指すPostgres拡張。
https://github.com/paradedb/paradedb/blob/dev/pg_search/Carg...
「Extending Postgres for High Performance Analytics (with Philippe Noël)」を聞いて知った。
https://www.youtube.com/watch?v=NbOAEJrsbaM
そして中核プロジェクトであるQuickwitにも入っている。ログ、トレース、まもなくメトリクスまで扱うプロジェクト。
https://github.com/quickwit-oss/quickwit
多言語検索の個人プロジェクトでQuickwitとClickHouseを一緒に使ってみたが、驚くほど良かった。ついに中国語、日本語、韓国語に使える組み合わせが出てきた。
https://quickwit.io/docs/guides/add-full-text-search-to-your...
PostgreSQLの
to_tsvectorは自分のユースケースではうまく合ったことがなかった。SELECT * FROM dump WHERE to_tsvector('english'::regconfig, hh_fullname) @@ to_tsquery('english'::regconfig, 'query');うまくいくことを願っている。Tantivyがキーワードに入った記事は自動でおすすめ投票してしまいそう。
最近Tantivyベースで、同じチームが作ったQuickwitを本番環境にデプロイし、数十億個のオブジェクトをインデックスしたが、とても満足している。インデックス速度が素晴らしく、クエリのレイテンシも競争力がある。
何より重要なのは、コンピュートとストレージの分離が非常に大きな価値をもたらしたことだ。長時間稼働する高性能サーバーのコストを払わずに、オブジェクトストレージ上の数十億個のオブジェクトに対して新しい検索サービスを立ち上げ、複雑な集計までできるため、本来ならかなり高くついたはずの新しいユースケースが可能になった。
ユースケースが高性能サーバーを正当化できる規模になれば、Quickwitは各サーバーにデータをキャッシュして性能を高める選択肢も提供している。
大きなボーナスとして、Discordでチームが非常に迅速かつ親切に助けてくれる。
もう1つの資料としては、etsy/hound[0]で使われているGoベースのトライグラム検索インデックスがある。Russ Coxの記事とコード「Regular Expression Matching with a Trigram Index」[1]に基づく。
[0] https://github.com/hound-search/hound
[1] http://swtch.com/~rsc/regexp/regexp4.html
必要に応じて、Luceneの代替もユースケースが変わってくる。
注意すべき点は、今でも フィールドの追加/削除 ができないこと: https://github.com/quickwit-oss/tantivy/issues/470
フィールドを追加する唯一の方法は、すべてのデータを別の検索インデックスに再インデックスすること
デフォルトでテレメトリデータを送信する Meilisearch の代替を探していて Tantivy を見つけた。検索エンジンそのものというよりは 検索エンジンビルダー に近いが、設定はかなりシンプルに見える [0]
[0]: https://github.com/quickwit-oss/tantivy-cli
Meilisearch の Java SDK も良かった。CLI や手動設定が不要で、データベースエンティティを指すだけでテーブル全体をインデックス化できた
Tantivy でもそういう方法があるといい
Tantivy は LanceDb という興味深い ベクトルデータベース 製品でも全文検索機能を提供するために使われている: https://lancedb.github.io/lancedb/fts/
最後に見たときは Python バインディング経由でしか使えなかったが、他のプラットフォームをサポートするために Rust バインディングをネイティブ実装しようとしていると理解している
数年前、Elasticsearch があまりに リソース食いの怪物 で、ものすごく苛立って個人プロジェクトを始めた。自分の個人PCでさえ、資金に余裕のある複数のスタートアップが製品に割り当てるより多くのリソースを持っていたにもかかわらずだ
Tantivy を選んだ理由は2つあった。1つはすべて Rust で作りたかったこと、もう1つは Tantivy そのものだった。性能は 10/10 で、ドキュメントは最高水準、ライブラリとしての使い心地も非常に良い
残念ながら、余暇に一人で扱うにはプロジェクトの範囲が大きすぎて諦めたが、それでも Tantivy は本当に素晴らしい
Tantivy をしばらく見守っていた。創業者たちの 粘り強さ と、最近 Tantivy が達成した性能には感銘を受ける
チーム全体に大きな拍手を送りたい。彼らが目標を達成すると強く信じている
Lucene と Solr をかなり使ってきた立場として一番望むのは アップグレード対応 だ。通常、Lucene、Solr、ES のインデックスは新バージョンへアップグレードできない。場合によっては可能だが、ここでは便宜上除外する
大規模プロジェクトでは再インデックスは非常に高コストで、ときにはほぼ不可能な作業になる
絶対に不可能である可能性が高い場合もある。たとえば、損失のあるインデックスフィールドでデータ型のインデックスアルゴリズムが変わった場合がそうだ。しかし多くの場合はすべての情報が残っているので、そうしたインデックスを識別してアップグレードできれば本当にありがたい