Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
OpenSearchでレガシーな検索処理の大幅改善をやってやろう
Search
DPon
April 12, 2025
Technology
2
330
OpenSearchでレガシーな検索処理の大幅改善をやってやろう
DPon
April 12, 2025
Tweet
Share
More Decks by DPon
See All by DPon
つよつよな人の理解の早さを理解する
dznbk
0
91
テスト書きたいけど 書けてないのは 何でなんだぜ
dznbk
0
130
php-fpmのプロセスをコントロールする
dznbk
0
10
Other Decks in Technology
See All in Technology
ここ一年のCCoEとしてのAWSコスト最適化を振り返る / CCoE AWS Cost Optimization devio2025
masahirokawahara
1
1.5k
大「個人開発サービス」時代に僕たちはどう生きるか
sotarok
19
9.3k
Language Update: Java
skrb
2
280
複数サービスを支えるマルチテナント型Batch MLプラットフォーム
lycorptech_jp
PRO
0
220
AI駆動開発に向けた新しいエンジニアマインドセット
kazue
0
260
おやつは300円まで!の最適化を模索してみた
techtekt
PRO
0
280
AIのグローバルトレンド2025 #scrummikawa / global ai trend
kyonmm
PRO
1
240
2025年夏 コーディングエージェントを統べる者
nwiizo
0
110
なぜテストマネージャの視点が 必要なのか? 〜 一歩先へ進むために 〜
moritamasami
0
170
LLMを搭載したプロダクトの品質保証の模索と学び
qa
0
910
今!ソフトウェアエンジニアがハードウェアに手を出すには
mackee
10
4.4k
Snowflakeの生成AI機能を活用したデータ分析アプリの作成 〜Cortex AnalystとCortex Searchの活用とStreamlitアプリでの利用〜
nayuts
0
360
Featured
See All Featured
Unsuck your backbone
ammeep
671
58k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
Typedesign – Prime Four
hannesfritz
42
2.8k
Scaling GitHub
holman
463
140k
A better future with KSS
kneath
239
17k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Java REST API Framework Comparison - PWX 2021
mraible
33
8.8k
Reflections from 52 weeks, 52 projects
jeffersonlam
352
21k
Speed Design
sergeychernyshev
32
1.1k
A designer walks into a library…
pauljervisheath
207
24k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.4k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Transcript
OpenSearchでレガシーな検索処理の 大幅改善をやってやろう PHPカンファレンス小田原2025
自己紹介 • 堂薗 伸樹(どうぞの のぶき) / DPon(@DPontaro) ◦ 園 薗 •
職業:エンジニア • 所属:スターフェスティバル株式会社 • 家族:妻 子👦👦 犬 • ゲーム好き • 大阪からきました • 🎉 カンファレンス初登壇 🎉
会社とサービスの話 • https://gochikuru.com/ • 法人・団体向けの宅配弁当 ケータリング・オードブルの デリバリーサービス。
前段 プロジェクトの説明
プロジェクトの特徴 • ごちクルとは別の特定業界向けのお弁当デリバリーサービス • Initial Commitは2015年 • コロナ禍で需要減。リソース都合もあり、しばらく専任のエンジニアがついていない 状態。 •
ときどき改善依頼があった際、手が空いてる人がスポットでアサインされる
パフォーマンスの課題 • 2024年春、サイトのパフォーマンスは少し触れただけでも体感できるくらいに悪い • 需要が戻りつつあるなか、マイナスの印象を与えるわけにもいかない
レガシーな環境
初手の改善
ボトルネックをみつける 商品検索のController。 リクエストされる頻度高く、かつ重い ページ。 中央値が 1.9 sec これに加え、ページ表示までに画像や cssのダウンロードなども発生する
初手の改善 スロークエリに手を入れてみる • INDEXの追加 • 該当箇所のコードを調整し、発行されるクエリを修正 結果200msec くらいは改善したが焼け石に水。
さてどうしたものか 長年専任がついていないプロジェクト、コードはツギハギで無駄も多い。 複雑に絡み合ったコードの解消のために、検索ロジック全体を組み直す必要がありそ う。 → それならもう OpenSearch に移行してもいいのでは?
OpenSearchとは • 分散型の検索エンジン。Elasticsearchのフォーク版 • クラスタ構成、複数のノードにデータ分散。 • 高速な全文検索が可能
簡単に用語解説:Document • Document:データを格納する単位。JSON形式。 ◦ 学生のデータベースでは、 Documentは1人の学生を表せる ◦ RDBにおける行に相当
簡単に用語解説:Index • Index:Documentの集まり ◦ RDBでいうテーブル ◦ 学生のデータベースでは、 Indexはすべての学生を表す
簡単に用語解説:Clusterとか • Cluster, Node ◦ Clusterは、Nodeの集まり。 ◦ Nodeはデータを保存、検索リクエストを処理 するサーバ。 •
Shard ◦ いわゆる水平分割。 ◦ Indexのdocumentを行単位でシャード分割し て分散 ◦ シャードの分割目安:シャードのサイズを 10 ~ 50 GB に制限することです。(公式いわく)
OpenSearchへの移行
OpenSearch公式のPHPクライアント まぁバージョン下げたら対応してるやつあるやろ。 https://github.com/opensearch-project/opensearch-php
おっかしいなー
真面目にどうするか 理想はPHPのバージョンアップ。そうはいっても • スポット的なアサインでもあり、メインは別プロジェクトの人員 • 元のミッションはパフォーマンス改善。 →バージョンアップはスコープ外では? • 認知負荷の高いコードの理解、スロークエリの対応など既にある程度時間もかけて いる。
→このタイミングからバージョンアップまでやる? ※言わずもがなテストはメンテされておらず
戦略的後回し // TODO PHPバージョンアップ 結局公式のPHP7.3が対応してるバージョンのクライアントを落としてから、7.1で動くよう にエラーが出る箇所をつぶして対応させました。 ※バージョンアップはパフォーマンス改善後に対応しました(7.4までですけど...
バッチの実装 毎時 RDS -> OpenSearch へデータ投入するバッチを実行。 その際”YYYYMMDD-HH”のサフィックスを持つINDEXが作成される。 例:product-index-20250412-15 INDEX作成後、アプリケーションが参照している OpenSearchのINDEXのエイリアスを変更。
実行前:product_index -> product-index-20250412-14 実行後:product_index -> product-index-20250412-15
マッピングの話 マッピングはOpenSearchに、ドキュメントとそのフィールドの保存方法とインデックスを指示します。 各フィールドのデータ型を指定することで (例えば、年を日付にするなど )、保存やクエリをより効率的に行うこと ができます。 Dynamic mapping (動的マッピング) 新しいデータやフィールドが自動的に追加される。
Explicit mapping (明示的マッピング) 推奨。正確な構造とデータ型を前もって定義できる。 パフォーマンスや正確性を高めることができる
マッピング一例 "id": map[string]string{"type": "integer"}, "product_name": map[string]interface{}{ "type": "text", "analyzer": "product_index_analyzer",
"search_analyzer": "product_search_analyzer", },
analyze 文字列を検索に使えるように「分かち書き(トークン化)」&「正規化」する処理
analyzer と search_analyzer "product_name": map[string]interface{}{ "type": "text", "analyzer": "product_index_analyzer", "search_analyzer":
"product_search_analyzer", }, analyzer:インデックス時(保存時)に使用する analyzer を指定。 search_analyzer:検索時に使用する analyzer を指定
synonym_filter search_analyzer には上記のsynonym_filterという同義語の設定がされている。 この設定により曖昧検索に対応できる "synonym_filter": map[string]interface{}{ "type": "synonym", "synonyms": []string{
"ウナギ,ウナジュウ", "子供,お子様",
やってみてどうだった
🎉結果発表🎉 before 中央値:1.9sec after 中央値:0.92sec
売上につながった? ここ1年で売上の数値はしっかり伸びている 🎉 複数要因があるものではありますが、パフォーマンス改善で下支えが出来た ※余談 社内の営業の方々から直接 DMでめちゃ助かったと何人か声かけていただいて、好感触
他改善するなら • 毎時のバッチ実行 ◦ 日々商品のデータは更新されているが、最大 1時間の遅延を許容している状態 ◦ よりリアルタイムに更新したい場合、イベント駆動な仕組みを取り入れたり • インフラのあいのり
◦ ごちクルと同じインスタンスなので障害発生した際は、どちらも検索処理が機能しなくなる(今のとこ ろ発生はしていない) ◦ 切り離せば懸念はなくなるが、コスト増にはなるのでバランス考えて • synonym_filterなどがコード中に定義されている ◦ 変更の際にエンジニアの手が入る状態となっているので、できれば外部ファイルに逃がしたほうが 良い