全文検索のためにAlgoliaを採用すべきかコスト面から検討する

#Overview

NoSQL系だとなかなか全文検索をサポートしている製品はまだ見たことがない。FirebaseのCloud Firestoreもしかり。
FirebaseのドキュメントではAlgoliaのようなSaaSの利用を勧めている。
https://firebase.google.com/docs/firestore/solutions/search?hl=ja

Firestoreに転置インデックス作って何とかならないかな？と思っていたら、@oukayukaさんが完璧な形で実装して記事化していた:joy:
[Firestore だけで Algolia を使わず全文検索](https://qiita.com/oukayuka/items/d3cee72501a55e8be44a)
サンプル触った限り、全文検索だけならこちらのほうがコスト的には優れているのは間違いないだろう。
[Firestoreは検索向けの料金体系ではない](https://firebase.google.com/docs/firestore/pricing?hl=ja#tokyo)ため、条件は異なるものの桁違いに安いからだ。

ということで、Algoliaの採用で進もうとしていたが、コスト面で気になる点があったので一度立ち止まって検討した過程をメモしておく。
正直なところ、調査途中でプレミアムクラスのサービスということが判明し、惰性で結論までもっていった内情がある。
そのため、一部手抜きに見える箇所があるかもしれないがご了承願います:bow:

#Target reader

- Firebaseを利用して全文検索の実装を検討している方。
- Algoliaの採用を検討していてコストに余裕のない方。

#Prerequisite

- 30ドルのSTARTERプランを検討。


#Body

##Algoliaの料金体系をみる

https://www.algolia.com/pricing/

Developerレベルで月に約30ドルと500ドル…:fearful:
Freeプランがあるので導入しやすい反面、500ドル(更に従量部分あり)を請求するのはかなり高級なSaaSなんじゃなかろうかと、危機感を覚える。
そうなるとプランにどの程度の使用量が含まれているのか見ていく必要がある。
(PROを超えるEnterpriseは人生でかかわることはないので対象外)

| 項目             | COMMUNITY         | STARTER          | PRO             |
|:-----------------|:-----------------|:------------------|:----------------|
| オペレーション         | 5万          | 25万              | 500万          |
| レコード               | 1万           | 5万              | 100万         |
| オペレーション（超過）  | 超過不可       | 10万につき10ドル | 10万につき5ドル |
| レコード（超過）       | 超過不可      | 2万につき10ドル   | 2万につき5ドル  |
| レコード最大           | 超過不可        | 1000万        | 1000万          |

やばさを感じていただけただろうか？
STARTERを検討していたが、5万レコード以上は超過料金が発生する。
**10万レコードにしようとしたらトータルで50ドル確定。**
そもそも10万レコード自体、1ユーザーにつき100レコード消費すると仮定すると、1000ユーザーしか収容できない。
現実的にはけた違いの数が必要になる。
この時点で、ユーザーがコンテンツを保存するような製品に採用するのは、相応のコストを支払う必要があることがわかる。

レコードだけで危機感を覚えていただけただろうが、まだオペレーションの話が残っている。
途中退出は早すぎるよ？:wink:
オペレーションの具体的説明は、価格ページの下部の質問事項に載っている。

>What is an operation? How do you count operations?
For operations, we count both indexing operations and search operations:
>
>What is an indexing operation: An operation is counted when a record is added, updated or deleted. If you perform a batch update containing N records, it will count for N operations.
What is a search operation: A search operation is counted when a search is performed. In autocomplete and search-as-you-type implementations, a new search is performed on every keystroke. In case your search engine is querying N indices at each keystroke (a product index, a brand index, a categories index, etc.) then one keystroke will correspond to N operations.
For more details, please refer to our detailed documentation.
>
If fewer operations are used than included in the plan or than purchased with overage, they do not roll over to the following service period.

私が訳してもいいのだが、ここはGoogle翻訳に譲ろう:wink:
先生お願いします。

>操作とは何ですか？オペレーションのカウント方法は？
操作については、インデックス作成操作と検索操作の両方をカウントします。
>
インデックス作成操作とは：レコードが追加、更新、または削除されたときに操作がカウントされます。N個のレコードを含むバッチ更新を実行すると、N個の操作がカウントされます。
検索操作とは：検索が実行されると、検索操作がカウントされます。オートコンプリートおよび入力に応じた検索の実装では、キーストロークごとに新しい検索が実行されます。検索エンジンが各キーストロークでN個のインデックス（製品インデックス、ブランドインデックス、カテゴリインデックスなど）をクエリしている場合、1つのキーストロークはN個の操作に対応します。
詳細については、詳細なドキュメントを参照してください。
>
計画に含まれているよりも少ない操作を使用した場合、または過剰に購入した操作よりも少ない操作を使用した場合、次のサービス期間にロールオーバーされません。

詳細ページはこちら。
https://www.algolia.com/doc/faq/accounts-billing/how-algolia-count-records-and-operation/

ここにある例をGoogle翻訳先生を通じて引用する。

>レコードカウントのロジックを説明する前に例を見てみましょう。
>
メインインデックス内の5000オブジェクト
3つのレプリカインデックス
合計レコード：5000 x 4（プライマリインデックス1 +レプリカ3）= 20,000レコード
レコードの数は、すべてのインデックス（レプリカインデックスを含む）にあるレコードの合計に等しくなります。

(中略)

>インデックス作成または検索操作のいずれかであるすべての操作に対して料金を請求します。
>
最初に例を見てみましょう：
>
1か月あたり40,000オブジェクトの更新
1日あたり20,000の検索操作= 1か月あたり600,000（30日間の場合）
1か月あたりの合計操作数：640,000（インデックス操作+検索操作）

計算の前に…レプリカって料金表では全く出てなかったと思ったが…結論が見えたのであえて無視する:joy:

まずレコード操作については、1レコード1オペレーションなので、1万レコードをアップデートしたら1万オペレーション。理解した。
次に検索操作については、1クエリー1オペレーションなので、1万回検索したら1万オペレーション。理解した。
オペレーションにはまだ説明があり、

>検索操作は、検索が実行されるときにカウントされます。オートコンプリートおよび入力時検索の実装では、検索はキーストロークごとに実行されます。検索エンジンが各キーストロークでN個のインデックス（製品インデックス、ブランドインデックス、カテゴリインデックスなど）をクエリしている場合、1つのキーストロークはN個の操作に対応します。

つまり、オートコンプリートにしようものなら、キー入力ごとに検索するため、1回の検索で数回のオペレーションが走るということ、理解した。
重複検索はキャッシュする旨の記述があるが、もう答えは出たので大丈夫だ。:thumbsup:


#Conclusion

考察ではSTARTERプラン（レコード5万、オペレーション25万）を扱う。
ユーザー数については1000人としておく。

まずレコードについて。
レコードはレプリカ分を含むが、STARTERでレプリカいくつか不明のため、最低条件としてレプリカは0として考える。
超過しない場合、ユーザー1人当たり50レコードしか使用できない。
そもそも50レコード程度なら検索する必要はなく、最低でも30ドル払って100レコードは必要になるだろう。

次にオペレーションについて。
クエリーを除いたオペレーションではレコード数分消費するため、すべてのユーザーが250回追加、更新、削除しようものなら消費し尽くしてしまう。
クエリー以外のオペレーションは高価であると認識すべき。

クエリーの場合、オートコンプリートはオペレーションの消費を加速するため、検索ボタン押下で消費を抑えたい。
消費を抑えればユーザーは月に250回もの検索が可能になる。1日当たり約8回検索可能。

…( ´Д｀)=3 ﾌｩ

もう理解できているだろうが、1000人レベルでSTARTERプランはかなり厳しい。
無料から利用できるからとりあえず導入したら後々コスト面で頭を抱えることになる。
Algoliaは資金的に余裕のあるEnterprise向けの高コスト高パフォーマンスの製品なんだろうというのが結論。
これを運用に採用できるPJは以下のようなケースだと思われる。

- **レコードは基本的に更新されない(オペレーションの頻度が低いことが重要)。**つまり想定シーンはサイト運営側でデータを提供する形態。
- レコード数は5万を大幅に超えない。

一言でいえば圧倒的に検索にオペレーションを回せる、アーカイブ的なコンテンツに限り採用可能と結論付ける。
それ以外ではどこかで超過分が出るため、想定されるオペレーションの計算を怠らないようにしたい。
もしくはElasticsearch等の製品を探してみるのも一手。（料金がAlgolia以下になるかは不明）
https://www.elastic.co/jp/products/elasticsearch/service/pricing


#Appendices

なし。

#References

インタビュー: 超高速リアルタイム検索APIサービス「Algolia」の作者が語る高速化の秘訣（翻訳）
https://techracho.bpsinc.jp/hachi8833/2018_06_20/57589

ElasticSearch vs Algolia
https://medium.com/@matayoshi.mariano/elasticsearch-vs-algolia-96364f5567a3

Azure Cognitive Search でのフルテキスト検索のしくみ
https://docs.microsoft.com/ja-jp/azure/search/search-lucene-query-architecture

Cloud Firestore Best practices
https://cloud.google.com/firestore/docs/best-practices?hl=ja

Cloud Firestore 割り当てと上限
https://cloud.google.com/firestore/quotas?hl=ja

Azure Database
https://azure.microsoft.com/ja-jp/product-categories/databases/
Azure DataExplorer
https://azure.microsoft.com/ja-jp/pricing/details/data-explorer/
Azure クエリー言語
https://docs.microsoft.com/ja-jp/azure/kusto/query/