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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
shunta ichikawa
March 19, 2026
Programming
210
1
Share
見せてもらおうか、 OpenSearchの性能とやらを!
shunta ichikawa
March 19, 2026
More Decks by shunta ichikawa
See All by shunta ichikawa
メンテが命: PHPフレームワークのコンテナ化とアップグレード戦略
shunta27
0
730
20240711_RAGを用いたシンプルな 社内情報検索システムを導入した話とつらみ
shunta27
2
5.6k
Other Decks in Programming
See All in Programming
Kingdom of the Machine
yui_knk
2
1.4k
GitHubCopilotCLIをはじめよう.pdf
htkym
0
330
アクセシビリティ試験の"その後"を仕組み化する
yuuumiravy
1
200
ハーネスエンジニアリングにどう向き合うか 〜ルールファイルを超えて開発プロセスを設計する〜 / How to approach harness engineering
rkaga
28
19k
Import assertionsが消えた日~ECMAScriptの仕様はどう決まり、なぜ覆るのか~
bicstone
2
180
過去のレビュー知見をSkillsで資産化した話
pkshadeck
PRO
1
1.5k
Programming with a DJ Controller — not vibe coding
m_seki
3
790
JAWS-UG横浜 #100 祝・第100回スペシャルAWS は VPC レスの時代へ
maroon1st
0
220
(Re)make Regexp in Ruby: Democratizing internals for the JIT
makenowjust
3
1k
PicoRuby for IoT: Connecting to the Cloud with MQTT
yuuu
2
760
Agent Skills を社内で育てる仕組み作り
jackchuka
1
1.5k
Claude Code × Gemini × Ebitengine ゲーム制作素人WebエンジニアがGoでゲームを作った話
webzawa
0
220
Featured
See All Featured
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
Visualization
eitanlees
150
17k
Bash Introduction
62gerente
615
210k
The Curse of the Amulet
leimatthew05
1
12k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
280
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Ethics towards AI in product and experience design
skipperchong
2
270
Scaling GitHub
holman
464
140k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
160
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は伸びなかった だからこそ、 技術課題と事業課題を切り分けて考えることが大事 まとめ
皆様、ご清聴ありがとうございました!