いろいろあって Elastic Cloud がオススメな件

MySQLのインデックスの代わりにElasticsearchを使おうと思い立っていろいろやってみた結果、Elastic社のホスティングけっこうオススメなんじゃないかってなった話です。これです:

www.elastic.co

経緯としては、AWSにのっけたサービス、とりあえずMySQLとRedisだけでやってきた仕組みが、そろそろノーキャッシュ新規クエリ単発で1秒以上かかる場合が出てきたというのがあります。

アプリケーションで決まったパターンの問い合わせだけやってるぶんには、問い合わせのパターン数だけ複合インデックを作ればいいし、負荷分散したければリードレプリカが簡単、ということでほとんどの場合MySQLでいいのですが...

  • MySQLは個別のインデックス勝手に組み合わせてくれない、全パターン定義しないといけない
  • 管理者が使う検索機能のよっては、想定したインデックスにうまくヒットしない条件になる
  • どうしてもORが必要でほぼフルスキャンになることがある
  • B-Treeの末端が5件だったり10万件だったりとカーディナリティの偏りがひどい
  • 日本語ではMySQLのフルテキストがつらい

などあって、状況に応じてMySQLのキメキメインデックスとElasticsearchを使い分けたらどうかと。

で、手元で検証したかぎりでは、これがものすごくうまくいきました。HTTPレスポンスの段階で10倍ぐらい速くなりました。日本語についても、形態素解析がんばらなくても、固定長のN-Gramでバラしてmatch_phraseで当てれば、SQLでいうLIKEと同じ結果を得られました。

あとは実プロダクトに使うだけで幸せになれるぜと、同じAWSがやっている Elasticsearch Service でやってみることに。ちょっと認証まわりでひと苦労ありましたが、どうにか接続はできました。

tanakahisateru.hatenablog.jp

プラグインとかはどうするんだろう、と思いつつも、まあ目的がB-Tree一本勝負の代替だし追加機能とかなくていいや、これでもう勝ったなと思うじゃないですか。思ったんですよ。けど現実は厳しいんですよ。

こんなんじゃ1リクエストで2回問い合わせたらもうMySQLフルスキャンと同じ...

@johtani さんに助けてもらいつつ...

Elasticsearchインデックス作成におけるパフォーマンス考慮事項 | Elastic

EBSとインスタンスストレージで比較したり、ノード数を減らしてみたりしたものの、ほとんど結果は同じ。まあ並列書き込みはすごく安定しているのでありがたいんですが、もしかしたら何か用途が間違っているのではないかと気付きはじめます。

Elasticsearchの結果に含まれる took 値は、クラスタ内で何ミリ秒で処理が終わったかを指す値、それと実際のHTTPレスポンスの差を比較するといいみたい。もしかしてこれ、ログとかを大量に書き込んで後でまとめて解析するためのサービスなのでは...

そこで試しに、同じVPC内に同等スペックのEC2インスタンスを立てて、2ノードのクラスタを組んでみたら、あっさり10倍性能出ました。めでたしめでたし。

では終わらないですよ。

これだけ助けてもらってトライアルしないとかダメでしょ絶対。ものは試しだえーい。

f:id:tanakahisateru:20160601175239p:plain

うわ、なにこれこんな簡単にクラスタ組めるの? スペック決めてTokyo選んでシャード数決めただけ。管理ツールとかプラグインとか全部入りで最新バージョンでセキュリティ設定もブラウザで可能で、ふむふむ接続はElasticsearch標準のHTTP認証だからクライアントライブラリもそのまま使えて...

とは言ってもインターネット越しだからEC2からEC2よりは遅いよね... え、ええっ!! 同等レイテンシー?!

はい

The Official Hosted Elasticsearch & Kibana Offering on AWS

on AWS なのです。Tokyoってのはつまり、AWSのTokyoリージョンのデータセンターのこと。EC2にがんばって黒い画面でクラスタ組んだのと同じ。うわぁ...

高いスペックを要求すればかなりの価格になりますが、単純にコンテンツの全文検索を速くしたいぐらいのニーズなら、最低スペックかその次ぐらいで十分で、そのあたりはお値段もかなりリーズナブルです。一番安いプランだと、たとえば月あたり1万円かけずに100〜200万件の全文検索を20〜80msでできる(ざっと見積りでそれぐらい)感じ。スロークエリのピーク負荷逃がし用のリードレプリカを1個つ増やすより断然安いですよね。

大規模なサービスの全トラフィックを集めるとかではなく、素朴に、コンテンツ検索でMySQLのフルテキストインデックスの代わりに使うとかなら、たぶんディスクは16GBもあれば十分。ユーザーの全行動追跡みたいなのは無理でも、直近3年のショッピングカートの出し入れ傾向ぐらいならぜんぜん余裕なんじゃないでしょうか。足りなくなったら上げればいいんだし。てか、これスペック上げるって時点でもう黒字サービスなはずですよきっと。というわけで、管理の簡単さもあって、AWSでスロースタートするのにとてもやさしいサービスだなと思いました。

ちょっと微妙な点としては、メモリとディスクが別々に選べないってところです。まあ多分スケール単位が仮想マシンじゃなくて、ノードなんだろうな、ってことで難しそうですが、もしCPU/メモリ/ディスク/IOを細かく指定できたら、もっと価格に柔軟性が出そうです。

自分の場合、意味のあるデータとそれへの検索クエリに対して、あまり使わないけど入れとかないといけない眠ったデータが大量にあって、ああこれ、CPUとメモリをケチってディスクを大きくできたらなーってのがあり、今回はEC2の自作クラスタを使うことにしました。

逆にいうと、データの重要度に偏りがなくてメモリ/ディスクのバランスがマッチするなら、どう考えても Elastic Cloud でスタートするのまじでオススメ、ってことです。とくに受託でやってる人とか、黒い画面での管理じゃなくて、アカウントとブラウザのGUIで引き継げるからってことで、だいぶチャレンジしやすいんじゃないでしょうか。

まとめ

  • AWSのElasticsearch Searviceほど素のElasticsearchと違わない
  • クラスタ構築をGUIでできる
  • プラグインや管理ツールが標準で入ってる
  • 小規模(100万件程度)で使うならすごくリーズナブル
  • 画面があるので引き継ぎやすい
  • クラスタAWSの中にある
  • さすが本家の公式

毎日SQLのパフォーマンスに苦しんでいる人、Elasticsearch チャレンジしてみてはどうでしょう?

え? トライアル期間が14日しかないのに習得するのはつらい? いやいやAWSなら t2.micro を1年使えますよね。てか、技術的に学びたいだけなら、zipで落として自分のJavaで動かせばいいんですよ。クラウドにしかないサービスと違って、これ基本OSSですよ。それ済んでからの14日トライアルぜひ。