Groongaの開発に参加している須藤です。今年も年に一度の肉の日(2月9日のこと)が来ましたね!例年通り、GroongaとMroongaはメジャーバージョンアップしました!今年はついでにPGroongaもメジャーバージョンアップしました!この一年でどのくらいGroonga・Mroonga・PGroongaがよくなったかを紹介します。
ちなみに、世間ではメジャーバージョンアップをすると互換性がなくなってアップグレードが大変!というソフトウェアが多いですが、Groonga・Mroongaは非互換なしなのでいつもどおり安心してアップグレードできます!PGroongaは非互換がありますが、普通は関係のない非互換なのでいつもどおり安心してアップグレードできます!そこらへんは後述します。
Groonga
Groongaは今回のメジャーバージョンアップで15.0.0になりました。
前回のメジャーバージョンアップからの目玉機能はここらへんになります。
- 特定ケースの検索パフォーマンス向上
- JSONのパースの高速化
- ラテン語系の言語のサポートを強化
- Unicode 16.0.0対応
- 生成カラムのサポート
- 言語モデルのサポート
- LGPL-2.1-onlyからLGPL-2.1-or-laterにライセンス変更
- パトリシアトライへのデフラグのサポート
- パラレルオフラインインデックス構築のサポート
それぞれ簡単に紹介します。
特定ケースの検索パフォーマンス向上
Groongaは広く公開しているフリーソフトウェアなので、Groonga開発者たちの知らないところでもたくさん使われています。(使われているはず!)もちろん、そういう使い方をしてまったく問題ないのですが、一部のユーザーはクリアコードが提供するGroongaサポートサービスを利用しています。
Groongaサポートサービスは基本的に時間制のサポートサービスになっていて、時間内であればかなりいろんなことに対応しています。高速化もその中の一つです。「高速化したい検索」をこちらで再現するためのデータとクエリーをお客さんから提供してもらって高速化します。クエリーレベルのチューニングをすることもありますが、多くの場合はGroongaの検索処理を改良して抜本的に高速化します。つまり、データ・クエリーはそのままでGroongaをバージョンアップしただけで高速になる、というような高速化をすることが多いです。
今回の期間にもそのような高速化が入っているので、バージョンアップしただけで速くなることがあるかもしれませんよ!もし、こういうケースで遅いんだよなーというケースがある場合はGroongaサポートサービスを利用して相談してください。GitHubのissueで無料で相談することもできますが、忙しいと対応が後回しになることもあるので、急いで速くしたい場合はサポートサービスの方が確実です。サポートサービスだと私たちが仕事の時間で対応できるのです。
JSONのパースの高速化
Groongaは実はJSONパーサーを3つ持っています。自前のJSONパーサーとRapidJSONとsimdjsonです。最後のsimdjsonが今回の期間で追加されたJSONパーサーです。RapidJSONでやっていた処理を置き換えています。
RapidJSONとsimdjsonを使っている部分は文字列から配列へのキャスト("[1, 2, 3]"
を[1, 2, 3]
にするとか)のところだけでそんなに大きなJSONにならないので、simdjsonにすることでそんなに高速にはならないはずですが、それでも高速にはなっているはずです。
ちなみに、大きなJSONをパースする可能性が一番あるload
コマンドは自前のJSONパーサーになっています。これはすでに結構高速なはずなのですが、もしかしたらsimdjsonの方が高速かもしれません。ただ、自前パーサーは多少壊れたJSONも受け付ける設計になっているので、マジメにパースするsimdjsonには簡単には置き換えられないんですよねぇ。。。
ラテン語系の言語のサポートを強化
Groongaはよみがな検索やローマ字検索など日本語サポートが充実していますが、他の言語のサポートもできる範囲で強化しています。できる範囲でというのは、開発者がわからない言語をいい感じにサポートするのが難しいからです。今回はレポートしてくれた人と協力して上に点がついているアルファベット(たとえば「ằ」 U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE)などの正規化をいい感じにしました。
Unicode 16.0.0対応
Unicodeはバージョンが上がるごとに対応する文字が増えたりしていて、日本語サポート強化はもちろん、日本語以外のサポートの強化にもつながります。
Unicode 16.0.0は去年リリースされた最新のUnicodeで、引き続き最新のUnicodeサポートを維持しています。
生成カラムのサポート
最近のデータベース管理システムにはよくある機能である生成カラムをGroongaでも使えるようになりました。生成カラムというのは中身が自動的に生成されるカラムです。たとえば、他のカラムの値に対して関数を呼んで加工したデータを生成したりします。他のカラムに従属するデータをデータベース管理システムがメンテナンスしてくれるのでアプリケーションがメンテナンスしなくてもよくなります。
これは次の「言語モデルのサポート」のために実装しました。
言語モデルのサポート
昨今はLarge Language ModelやSmall Language Modelなどの言語モデルの性能が飛躍的に向上しています。自然言語を扱うGroongaもそれらを活用するべくllama.cppの組み込みを始めました。
llama.cppは言語モデルの推論機能を使うための高速なライブラリーです。SIMDを使えるCPUがあればGPUがなくてもわりと高速に推論できます。(GPUがある方が高速ではあります。)
llama.cppにはテキスト生成機能があるので、おいおいはllama-serverみたいにOpenAI API互換のAPIを提供するとか、Ollama互換のAPIを提供するとかしてもいいかも?とは思っています。これらの互換APIを提供すると、既存のクライアントライブラリーを使い回せるのではないかというのが狙いです。が、今のところはまだテキスト生成機能は提供していません。
今のところはエンべディング生成機能だけを使っています。セマンティックサーチ対応のための準備です。前述の生成カラムを使ってエンべディングを自動生成できるようになっています。
Groongaがエンべディング生成機能を持っているので、アプリケーションはテキストを入力するだけでエンべディングも生成されます。今は、アプリケーションがエンべディングを計算してデータベース管理システムに入れる方法が主流ですが、エンべディングは結構なサイズになるので、転送量が大きくなりがちです。データベース管理システム内で生成できれば元テキストを転送するだけで済むので効率的だし、アプリケーションの開発も楽になるし、ウハウハでは?という狙いがあります。
LGPL-2.1-onlyからLGPL-2.1-or-laterにライセンス変更
GroongaはLGPL 2.1のみで利用できるフリーソフトウェアでしたが、LGPL 2.1以降のすべてのLGPL(現時点ではLGPL 3があるだけだけど)でも利用できるフリーソフトウェアになりました。
最近はフリーソフトウェアがライセンスを変更するという話があると、プロプライエタリなライセンスになる話が多いですが、Groongaはそうではありません!引き続きフリーソフトウェアで、使える自由なライセンスの選択肢が増えました!
パトリシアトライへのデフラグのサポート
Groongaのテーブルはハッシュテーブルやパトリシアトライで実装されていますが、その中のパトリシアトライをデフラグできるようになりました。
デフラグはフラグメンテーションを解消する処理ですが、パトリシアトライの場合はキーのフラグメンテーションを解消します。ようは追加削除を繰り返して使えない領域ができてしまっても、デフラグすることで使えるキーの領域を増やすことができます。
多くの場合はデフラグする必要がある状況にはならないはずですが、残念ながらなってしまった場合はデフラグすることでテーブルの作り直しを回避できます。
この機能の開発の様子に興味がある人は次のお話もどうぞ。
パラレルオフラインインデックス構築のサポート
複数のCPUコアを使うことにより高速にオフラインインデックス構築できるようになりました。データや空いているリソースに依りますが、数倍から10倍くらい高速になります。
もう少し知りたい人はGroongaの並列オフラインインデックス構築もどうぞ。
Mroonga
Mroongaは今回のメジャーバージョンアップで15.00になりました。
13系は開発リソースを確保できずにリリースがとぎれとぎれになってしまいましたが、14系ではペースを取り戻してきました。より開発を安定させたいユーザーはGroongaサポートサービスを検討してね。私たちが仕事の時間を使えるようになるから開発リソースを確保しやすくなります。
前回のメジャーバージョンアップからの目玉機能はここらへんになります。
- 最近のMySQL/MariaDB/Percona Server対応
- パラレルオフラインインデックス構築のサポート
- レアな型のサポートを強化
それぞれ簡単に紹介します。
最近のMySQL/MariaDB/Percona Server対応
MroongaはストレージエンジンAPIを使って実装されていますが、MySQL/MariaDB/Percona Serverはわりと頻繁にこのAPIを変更します。つまり、なにもしないとすぐにMroongaは動かなくなるのです!
ということで、MySQL/MariaDB/Percona Serverがリリースされたら動くかどうかを確認するCIを整備してあります。そこで問題を発見して直してリリースするということをしないとMroongaが陳腐化(古いMySQL/MariaDB/Percona Serverでしか動かなくなる)してしまうのです。
今回の期間もせっせと最新のMySQL/MariaDB/Percona Serverに追従しました。
また、MySQLの最新のLTSである8.4用のDockerイメージも提供し始めました。詳細はmroonga/dockerを参照してください。
パラレルオフラインインデックス構築のサポート
Groongaで使えるようになったパラレルオフラインインデックス構築機能をMroongaでも使えるようにしました。CREATE INDEX
速度を数倍にしたい人はぜひ使ってみてください。
レアな型のサポートを強化
今回の期間の開発の中で既存のコードを見直す機会があったのですが、そこでbit
型とyear(2)
型が動いていないことがわかりました。実装してからだれも問題を報告していないということは誰も使っていないということだとは思いますが、見つけてしまったのでいい感じに動くようにしてあります。
PGroonga
PGroongaは普段は2月9日にメジャーバージョンアップはしていないのですが、今回はちょうど前から入れたかった非互換の変更があったので、メジャーバージョンアップで4.0.0をリリースしました。
Groonga・Mroongaは基本的に非互換の変更を入れないように開発しているのですが、PGroongaではたまに非互換の変更を入れざるを得ないときがあります。今回は8年前に非推奨にしたpgroonga
スキーマを削除したかったのです。なにか忘れてしまったのですが、pgroonga
スキーマがあることで問題が発生することがあったのです。
8年前に非推奨にしたのでもうみんな新しいAPIに移行済みだよね?ということで、今回pgroonga
スキーマを削除することにしました。もし、まだ移行していない人は移行してからアップグレードしてください。
なお、PGroonga 2.1.4以前から使っている古参(?)PGroongaユーザーは4.0.1を使ってください。アップグレードに失敗する問題が見つかったので修正してあります。
前回のメジャーバージョンアップからの目玉機能はここらへんになります。
- カスタムWALリソースマネージャー対応
pgroonga_condition()
関数の追加- fuzzy検索のサポート
- パラレルオフラインインデックス構築のサポート
それぞれ簡単に紹介します。
カスタムWALリソースマネージャー対応
この機能があるとユーザーにとってなにがうれしいのかというと、ストリーミングレプリケーションがいい感じになります。従来は不要になったログを手動で消さないといけないとか、適用されていないWALが溜まってしまうとか、ユーザーがいい感じに設定したりメンテナンスしたりしないといけない部分がありました。が!この機能により、そういう面倒な部分がまるっとなくなります。便利でしょ?
この機能はPostgreSQL 15以降ではないと使えないので、新しいPostgreSQL/PGroongaにアップグレードして既存の仕組みから移行しましょう!
技術的な詳細に興味がある人はPGroongaでのカスタムWALリソースマネージャーの実装 #postgresqlをどうぞ。
pgroonga_condition()
関数の追加
PostgreSQLでは、検索条件はWHERE
の中で左辺 演算子 右辺
と指定します。「10以上」とかよくある条件はこれで十分表現できるのですが、全文検索などの高度なテキスト検索では十分表現できません。単純な全文検索は表現できますが、重みを変えるとか、誤字があっても検索できちゃうようにするかどうか(Googleでは「もしかして」と自動で修正済みのクエリーで検索するやつ)とかをコントロールできません。
ということで、右辺にテキストでクエリーを指定できるようにする(たとえばcolumn &@~ 'query'
とか)だけではなく、右辺に専用の型でクエリーを指定できるようにもしていました。これを使うと、たとえば、column &@~ ('query', ARRAY[5], NULL)::pgroonga_full_text_search_condition
のように詳細な検索条件を指定できました。が!長いし、新しいオプションを増やしたくなったら別の型を用意しないと後方互換性が壊れてしまう(PGroongaをアップグレードするとアプリケーションを変更しないといけない)という問題がありました。
それを解決するために導入されたのがpgroonga_condition()
関数です。これは前述の説明のような詳細な検索条件を表現した型を返すだけの関数なのですが、長いし互換性と拡張性のバランスが悪いという既存の問題を解決してくれるのです。この方法を思いつけてよかった。。。
pgroonga_condition()
自体がちょっと長めというのはありますが、新しいオプションを追加しても互換性のために別のより長い名前の関数(pgroonga_condition_with_XXX()
とか)を追加する必要はありません。なぜなら、PostgreSQLの関数はキーワード引数のように名前で特定の引数だけを指定して呼び出すことができるからです。たとえば、pgroonga_condition('query', fuzzy_max_distance_ratio => 0.34)
でfuzzy_max_distance_ratio
引数を指定して、他の引数はデフォルト値を使うということができます。(うーん、「長い」問題はあまり解決していないかも。。。)
この機能を活用することにより、pgroonga_condition()
に引数を追加しても互換性は壊れません。(アプリケーションを変更しなくても既存の呼び出しは動き続けます。)つまり、互換性を壊さずに新しいオプションを追加していけるし、インターフェイスはpgroonga_condition()
のままで済む(新しいpgroonga_full_text_search_condition_with_XXX
のような長い型を新しく導入しなくても済む)、ということです。
なんか、あまりうまく説明できていない気がしますが、互換性を維持しながら拡張していける基盤ができたすごい改良なのです!
fuzzy検索のサポート
先の例でちらっと出ていますが、全文検索時にfuzzy_max_distance_ratio
というオプションを指定できるようになりました。これを使うことにより、N文字誤字があっても自動で修正して検索してくれるようになります。
これは、typo tolerant検索とかとも呼ばれている機能で、ユーザーがすごい欲しい機能の1つなんですって!Groongaでは数年前から使えるようになっていますが、PGroongaでも使えるようになりました。
パラレルオフラインインデックス構築のサポート
去年の秋にリリースされたPostgreSQL 17から、拡張として実装されているインデックスでもパラレルオフラインインデックス構築を実装できるようになったのでPGroongaでも使えるようにしました。特に追加の設定は必要ないので、PostgreSQL 17で最近のPGroongaを使うとなぜかインデックス構築速度が速くなるはずです。
並列度はPostgreSQLが自動で算出した値を使っていますが、Groonga的にはPostgreSQLが算出した値よりも少しアグレッシブな並列度の方が性能がでる感じがしています。ここらへんは今後のリリースで改良するかも。
まとめ
年に一度の肉の日(2月9日)にGroonga・Mroonga・PGroongaをメジャーリリースしたので前のメジャーバージョンからの目玉変更を紹介しました。ぜひ最新のGroonga・Mroonga・PGroongaを使ってこれらの変更を活用してください。
Groonga・Mroonga・PGroongaをもっと使いこなしたい!という場合はGroongaサポートサービスを提供していますのでお問い合わせください。