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
shunta ichikawa
March 19, 2026
Programming
300
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
見せてもらおうか、 OpenSearchの性能とやらを!
shunta ichikawa
March 19, 2026
More Decks by shunta ichikawa
See All by shunta ichikawa
メンテが命: PHPフレームワークのコンテナ化とアップグレード戦略
shunta27
0
760
20240711_RAGを用いたシンプルな 社内情報検索システムを導入した話とつらみ
shunta27
2
5.6k
Other Decks in Programming
See All in Programming
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
570
AIとASP.NET Coreで雑Webアプリを作った話
mayuki
0
650
エンジニアと一緒にテストコードの設計と実装を改善した話
mototakatsu
0
200
AI 輔助遺留系統現代化的經驗分享
jame2408
1
260
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
710
AI時代のUIはどこへ行く?その2!
yusukebe
21
7.2k
ECSアプリログをFireLensでコスト削減しようとしたけど諦めた話 in Fargate×Node.js
akihisaikeda
2
4.2k
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
140
New "Type" system on PicoRuby
pocke
1
960
Performance Engineering for Everyone
elenatanasoiu
0
160
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
540
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
5.4k
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.5k
Crafting Experiences
bethany
1
180
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
210
From π to Pie charts
rasagy
0
210
My Coaching Mixtape
mlcsv
0
150
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
2.8k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
390
Thoughts on Productivity
jonyablonski
76
5.2k
Transcript
PHPerKaigi 2026
自己紹介 市川 俊太 いちかわ しゅんた (39歳) 株式会社助太刀 開発本部 開発部長 CTO
• 猫が好き • 趣味はサッカー観戦、ポケカ • Ruby/PHPなどのLL言語が好き
工事会社の人手不足を マッチング と正社員採用 で解決 会社紹介 受注者と発注者をつなぐ ビジネスマッチングサービス 建設業経験者向けの 求人サービス
OpenSearchとは • オープンソースの検索エンジン ◦ 2021年にAWSがElasticsearchをフォークして開発 ◦ ダッシュボード機能も存在(OpenSearch Dashboards) ◦ ドキュメント指向データベース
• 主な用途 ◦ 検索機能 ◦ ログ検索・分析 ◦ データ分析・ダッシュボード
Index / Document • Index = データの集合 • Document =
1件のデータ RDB OpenSearch Database Cluster Table Index Row Document Column Field Primary Key _id 基本構造(RDB / OpenSearch) Document Index
検索エンジンの仕組み(転置インデックス) 文書群から「単語」をキーにして「出現する文書IDや位置」を高速に検索するための索引構造 ID 職種 1 型枠大工 2 内装大工 3 型枠職人
単語 ID 型枠 [1, 3] 大工 [1, 2] 内装 [2] RDB OpenSearch LIKE '%型枠%' → 全件チェック 型枠 → [1, 3]
検索クエリの違い 「北海道で、型枠の仕事に関係する候補者を探す」 OpenSearchクエリ SQL
助太刀はマッチングプラットフォーム 🤝 主な検索機能 • 取引先検索 ◦ 例:職人さんを探す • 求人検索 ◦
例:建設会社の正社員求人を探す • 求職者検索 ◦ 例:企業が職人をスカウト ユーザ体験は「検索」から始まる
助太刀はマッチングプラットフォーム 🤝 主な検索機能 • 取引先検索 ◦ 例:職人さんを探す • 求人検索 ◦
例:建設会社の正社員求人を探す • 求職者検索 ◦ 例:企業が職人をスカウト (当時)検索機能は RDB(MySQL)を利用
結果 Laravelリクエストレイテンシ 約3秒 → 約500ms に改善
検索機能が抱えていた問題 • 検索条件の増加でSQLが巨大化 • Indexが効きづらい検索条件 ◦ LIKE / OR /
多段JOINなど • ページング用のCOUNTクエリが非常に重い → 結果として検索処理が遅い(平均3秒以上) SELECT … FROM candidates LEFT JOIN ... LEFT JOIN ... LEFT JOIN … WHERE speciality LIKE '%型枠%' OR ...
サービス展開の拡大 • Web版の提供 • ログイン前でも検索できるように変更 ◦ 検索流入・検索回数の増加 → 上記の施策が進行... 検索トラフィック増加!
サービス展開の拡大 • Web版の提供 • ログイン前でも検索できるように変更 ◦ 検索流入・検索回数の増加 → 上記の施策が進行... 検索トラフィック増加!
検索基盤としてOpenSearchを導入 • 提供しているサービスは Laravel で構築 • 検索機能は Eloquent を通して MySQL
を利用 Laravel / Eloquent と共存しながら 検索エンジンを OpenSearch に置き換え
OpenSearch と RDB を組み合わせた検索処理フロー OpenSearch RDB 1. 検索クエリ 2. ID一覧
3. Eloquent問い合わせ 4. レコード取得 検索サービス 北海道で、型枠の仕事に 関係する候補者を検索 検索はOpenSearch、正しいデータはRDB
OpenSearch と RDB を組み合わせた検索処理フロー
検索用データをOpenSearchに同期する OpenSearch RDB id name birth area speciality 123 市川工業
1987-02-07 北海道 型枠大工 Usersテーブル 同期 職種 Usersインデックス { "hits": { "hits": [ { "_id": "123", "_source": { "name": "市川工業", "area": "北海道", "speciality": "型枠大工" } }, …… ] } }
Laravel → OpenSearch OpenSearch RDB 1. 検索クエリ 2. ID一覧 3.
Eloquent問い合わせ 4. レコード取得 検索サービス
Laravel → OpenSearch Composerライブラリを利用 公式クライアント:opensearch-project/opensearch-php DSLクエリビルダー:shyim/opensearch-php-dsl
SQL検索をOpenSearchで表現する { "query": { "bool": { "must": [ { "wildcard":
{ "speciality": "*型枠*" } } ], "filter": [ { "term": { "area": "北海道" } } ] } }, "size": 10, "from": 0 } SELECT * FROM users WHERE speciality LIKE '%型枠%' AND area = '北海道' LIMIT 10 OFFSET 0; 1. SQL 2.OpenSearch DSL 3. クライアント実装
OpenSearch DSLをクエリビルダーライブラリで書く 3. クライアント実装 4. DSLライブラリ実装
DSLクエリービルダーライブラリを使う利点 • タイポ・構造ミスを防げる ◦ オブジェクトなら構造が保証される ▪ 配列だと must / filter
の入れ子を間違え やすい • 条件を動的に追加しやすい ◦ $query->add() のように積み上げられる ▪ 配列だとマージ処理が複雑 • IDE補完が効く ◦ クラス・メソッドが補完される 4. DSLライブラリ実装
Laravel → RDB OpenSearch RDB 1. 検索クエリ 2. ID一覧 3.
Eloquent問い合わせ 4. レコード取得 検索サービス
OpenSearchはID検索だけに使う OpenSearchの検索結果に含まれるID(_id)を 使ってEloquentで再取得する 検索結果のレスポンス構造 RDB id name birth area speciality
123 市川工業 1987-02-07 北海道 型枠大工 Usersテーブル 職種 同じIDで同期
OpenSearchはID検索だけに使う OpenSearchの検索結果に含まれる ID(_id)を使ってEloquentで再取得する 検索結果のレスポンス構造 • keyBy('id') で ID をキーにしたコレクションに 変換
• OpenSearch の並び順に合わせて map() で並び替える IDで再取得
• データの一貫性 ◦ OpenSearchはMySQLのレプリカで更新ラグがあるため、 Eloquentで再取得し最新データを保証。 • Eloquentのエコシステムをそのまま利用 ◦ OpenSearchのレスポンスは配列でありモデルマッピングが必要だが、 Eloquentで再取得すること
でリレーション・スコープ・アクセサなどの Laravel機能を利用可能。 • OpenSearchのスキーマを最小限に ◦ 検索に必要なフィールドのみ OpenSearchに持たせ、インデックスのメンテコストを削減。 • 責務が明確 ◦ OpenSearch:検索条件に合うIDリストを返す(全文検索、フィルタ、スコアリング) ◦ RDB (MySQL):そのIDに紐づくユーザーデータを返す(プロフィール、リレーションなど) OpenSearchをID検索だけに使うメリット
OpenSearchをID検索だけに使うデメリット • データストアに2回アクセスによるオーバーヘッド増大 • データ同期のタイミングによる不整合が発生しうる ◦ OpenSearch と RDB のデータが一時的に一致しないことがある
まとめ OpenSearchで検索性能は大きく改善できた Laravelと共存する現実的な移行もできた
OpenSearchで検索性能は大きく改善できた Laravelと共存する現実的な移行もできた でも、性能改善だけでは事業KPIは伸びなかった まとめ
OpenSearchで検索性能は大きく改善できた Laravelと共存する現実的な移行もできた でも、性能改善だけでは事業KPIは伸びなかった だからこそ、 技術課題と事業課題を切り分けて考えることが大事 まとめ
皆様、ご清聴ありがとうございました!