OpenSearch vs PostgreSQL:検索エンジンの選び方
「商品検索が遅い」「LIKE検索だと全然ヒットしない」—こんな悩みを抱えていませんか?
PostgreSQLでの検索に限界を感じてOpenSearchの導入を検討している方に向けて、両者の仕組みの違いと使い分けを解説します。
KEY TAKEAWAYS
この記事でわかること
- OpenSearchが高速な理由(転置インデックスの仕組み)
- PostgreSQLのB-Treeインデックスとの根本的な違い
- どちらを選ぶべきか判断するための具体的な基準
- PostgreSQL拡張で全文検索を実現する代替案
OpenSearchとは
WHAT IS
OpenSearch
Apache Luceneをベースにした全文検索エンジン。2021年にElasticsearchからフォークされたOSSで、AWS主導でLinux Foundation傘下のプロジェクトとして開発が続けられています。
WHY FAST
転置インデックス
「単語 → 文書」の逆引き辞書を事前に構築。検索時は辞書を引くだけなので、100万件でも数十ミリ秒で結果が返ります。PostgreSQLのLIKE検索とは根本的に異なるアプローチです。
Source: OpenSearch Documentation
転置インデックスの仕組み
OpenSearchが高速な最大の理由は「転置インデックス」にあります。本の巻末にある索引と同じ原理で、検索を劇的に高速化しています。
PostgreSQLのLIKE検索(フルスキャン)
通常のデータベースでLIKE '%ラーメン%'を実行すると、100万件のレコードを1件ずつ確認していきます。
これは本を1ページ目から全部読んで「ラーメン」という単語を探すようなものです。
- 計算量: O(n × m) ※n=件数, m=文字長
- 100万件で数秒〜数十秒かかることも
- インデックスが効かない(前方に%があるため)
OpenSearchの転置インデックス(辞書引き)
OpenSearchは事前に「単語 → 文書」の辞書を作っておきます。 検索時は辞書を引くだけなので、データ量に関係なく一定時間で結果が返ります。
- 計算量: O(1) 〜 O(log n)
- 100万件でも数十ミリ秒
- 複数単語のAND/OR検索も高速
B-Treeインデックス vs 転置インデックス
「PostgreSQLにもインデックスあるのに、なぜ全文検索が遅いの?」と疑問に思う方も多いでしょう。実は解いている問題が根本的に違います。
| 観点 | PostgreSQL B-Tree | OpenSearch 転置インデックス |
|---|---|---|
| 目的 | 値・範囲の高速検索 | 単語→文書の逆引き |
| 構造 | ツリー構造 | 辞書(ハッシュ的) |
= 'Sony' | O(log n) 高速 | O(1) 高速 |
LIKE '%ワイヤレス%' | インデックス効かない | O(1) 高速 |
BETWEEN 1000 AND 5000 | O(log n) 高速 | フィルタで対応可 |
| あいまい検索 | 別途pg_trgm等が必要 | 標準で対応(fuzziness) |
| 形態素解析 | なし | あり(「走った」→「走る」) |
B-Treeは「この値どこ?」を木構造で探す。転置インデックスは「この単語どの文書?」を辞書で引く。根本的に解いている問題が違います。
なぜB-Treeは中間一致が苦手なのか
B-Treeは「先頭から順に並んでいる」前提で設計されています。LIKE 'Sony%'(前方一致)なら「S」で始まる範囲を一気に絞れますが、LIKE '%ワイヤレス%'(中間一致)だと「どこから探せばいいかわからない」ため、結局全件スキャンになります。
OpenSearchが高速なその他の理由
転置インデックス以外にも、OpenSearchには高速化のための仕組みがいくつかあります。
トークナイズ(形態素解析)
日本語の文章を単語に分解し、検索可能にします。
- 「東京で人気のラーメン店」→ [東京, 人気, ラーメン, 店]
- ストップワード(で、の、は等)は除去
- Kuromoji等のアナライザーで日本語対応
セグメントとイミュータブル設計
データを「セグメント」単位で管理し、一度書いたら変更しない設計です。
- ロック不要で並列読み取りが超高速
- OSのページキャッシュに乗りやすい
- トレードオフ: 更新はRDBほど得意ではない
シャーディング(分散処理)
データを複数のシャードに分割し、並列で検索します。
- 100万件を5分割 → 5並列で検索
- 理論上5倍速い
- レプリカで可用性も確保
メモリ活用
できるだけデータをメモリに載せて高速化しています。これがOpenSearchが高コストな理由でもあります。
- JVM Heap: フィールドデータ、クエリキャッシュ
- OS Page Cache: セグメントファイル
- 推奨: 物理メモリの50%をJVM Heapに
Source: Instaclustr - OpenSearch and Elasticsearch Architecture
OpenSearchの本当の強み
JOINコスト削減は副次的メリット。本当の強みは「検索体験」を作れることです。
| 機能 | 説明 | PostgreSQLでの対応 |
|---|---|---|
| あいまい検索 | 「ワイヤレスイアホン」(typo)でも「ワイヤレスイヤホン」がヒット | pg_trgmで一部対応可能 |
| 関連度スコアリング | 検索キーワードとの関連度で順位付け | ts_rank関数である程度可能 |
| 形態素解析 | 「走った」で「走る」もヒット | PGroongaで対応可能 |
| ファセット検索 | 「カテゴリ別の件数」を一発集計 | GROUP BY + 複数クエリが必要 |
| ハイライト | マッチした箇所を強調表示 | ts_headline関数で対応可能 |
具体例:ECサイトの商品検索
実際のECサイトでどのように使い分けるか見てみましょう。
PostgreSQLの正規化テーブル
商品、ブランド、カテゴリ、タグ、レビューをそれぞれ別テーブルで管理します。正規化によりデータの整合性は保たれますが、検索時に多数のJOINが必要になります。
products: 商品マスタbrands: ブランドマスタproduct_categories: 商品×カテゴリの中間テーブルreviews: レビューテーブル
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255),
description TEXT,
price INTEGER,
brand_id INTEGER REFERENCES brands(id)
);
CREATE TABLE brands (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE product_categories (
product_id INTEGER REFERENCES products(id),
category_id INTEGER REFERENCES categories(id)
);PostgreSQLでの検索(辛いパターン)
商品検索で名前、ブランド、カテゴリ、レビュー評価を一度に取得しようとすると、JOINが5つ必要になります。さらにLIKE検索ではインデックスが効きません。
- JOINが5つ → 重い
LIKE '%...%'→ 全件スキャン- typoでヒットしない
- 関連度順にできない
SELECT p.id, p.name, b.name AS brand_name,
AVG(r.rating) AS avg_rating
FROM products p
LEFT JOIN brands b ON p.brand_id = b.id
LEFT JOIN product_categories pc ON p.id = pc.product_id
LEFT JOIN categories c ON pc.category_id = c.id
LEFT JOIN reviews r ON p.id = r.product_id
WHERE p.name LIKE '%ワイヤレスイヤホン%'
OR p.description LIKE '%ワイヤレスイヤホン%'
GROUP BY p.id, b.id
ORDER BY avg_rating DESC;OpenSearchのドキュメント構造
JOINを事前に解決して、1商品1ドキュメントで格納します。非正規化により冗長性は増しますが、検索は劇的に高速化します。
- 関連データをすべて1ドキュメントに
- JOINが不要
- 転置インデックスで爆速検索
{
"id": 12345,
"name": "Sony WF-1000XM5 ワイヤレスイヤホン",
"description": "業界最高クラスのノイキャン...",
"price": 36000,
"brand": { "name": "Sony", "country": "日本" },
"categories": [
{ "name": "オーディオ" },
{ "name": "完全ワイヤレスイヤホン" }
],
"tags": ["ノイキャン", "Bluetooth", "ハイレゾ"],
"rating": { "average": 4.5, "count": 328 }
}OpenSearchでの検索クエリ
1つのクエリで、あいまい検索、フィルタリング、ソート、ファセット集計がすべて実行できます。
fuzziness: typoでもヒット^3: nameフィールドを3倍重視aggs: ブランド別件数も一発取得
{
"query": {
"bool": {
"must": [{
"multi_match": {
"query": "ワイヤレスイアホン",
"fields": ["name^3", "description", "tags"],
"fuzziness": "AUTO"
}
}],
"filter": [
{ "range": { "price": { "lte": 50000 } } }
]
}
},
"aggs": {
"brands": { "terms": { "field": "brand.name.keyword" } }
}
}コストについて考える
OpenSearchは高機能ですが、その分コストもかかります。判断基準を見てみましょう。
| 項目 | AWS OpenSearch Service | PostgreSQL (RDS) |
|---|---|---|
| 最小構成 | 約$350/月〜(Serverless 最小) | 約$15/月〜(db.t3.micro) |
| 本番冗長構成 | 10万円/月超えも普通 | 数万円/月〜 |
| 無料枠 | t3.small.search 750時間/月 | db.t2.micro 750時間/月 |
| 運用コスト | シャード設計、インデックス管理 | 標準的なDB運用 |
OpenSearchを選ぶべきケース
- 検索がプロダクトの核(EC、メディア)
- 大量のログ分析・可視化が必要
- あいまい検索・ファセットが必須
- 将来的に大規模スケールが見込まれる
PostgreSQLで十分なケース
- 検索は「あれば便利」程度
- データ量が数十万件程度
- インフラコストを抑えたい
- トランザクションの整合性が最重要
Source: AWS OpenSearch Service Pricing
代替案:PostgreSQLで全文検索を実現する
OpenSearchを導入するほどではないけれど、LIKE検索の遅さは解消したい。そんな場合はPostgreSQLの拡張機能を使う方法があります。
| 拡張 | 用途 | 日本語対応 |
|---|---|---|
| pg_trgm | あいまい検索(trigram) | 一部動作する |
| PGroonga | 日本語全文検索(高機能) | 完全対応 |
| pg_bigm | 日本語全文検索(軽量) | 完全対応 |
| tsvector(組み込み) | 組み込みの全文検索 | 英語等のみ |
PGroongaを使った日本語全文検索
PGroongaはGroongaという全文検索エンジンをバックエンドに使用しており、日本語の形態素解析にも対応しています。PostgreSQLのテーブルにインデックスを作成するだけで使えます。
&@~: 全文検索演算子- recheckが不要で高速
- 更新中も検索性能が落ちない
-- PGroonga拡張を有効化
CREATE EXTENSION IF NOT EXISTS pgroonga;
-- 検索用の非正規化ビューを作成
CREATE MATERIALIZED VIEW product_search AS
SELECT p.id, p.name, p.description, p.price,
b.name AS brand_name,
p.name || ' ' || COALESCE(p.description, '') AS search_text
FROM products p
LEFT JOIN brands b ON p.brand_id = b.id;
-- PGroongaインデックス作成
CREATE INDEX idx_search_text
ON product_search USING pgroonga (search_text);
-- 検索
SELECT * FROM product_search
WHERE search_text &@~ 'ワイヤレスイヤホン';スモールスタートのすすめ
小〜中規模ならPostgreSQLの拡張(PGroonga等)でしのいで、本当に限界が来たらOpenSearch導入、というのが現実的なアプローチです。最初から大規模インフラを構築する必要はありません。
Elasticsearch vs OpenSearch:どちらを選ぶか
OpenSearchを検討する際に避けて通れないのが、Elasticsearchとの比較です。両者の違いを見てみましょう。
ライセンス問題とフォークの経緯
Elasticsearchは2021年にApache 2.0ライセンスからSSPL/Elastic Licenseに変更されました。これは厳密にはオープンソースではなくなることを意味します。
- 2015年: AWS「Amazon Elasticsearch Service」開始。Elastic社のコードを使ってマネージドサービス提供。
- 2021年: Elastic社がライセンス変更(SSPL/Elastic License)。AWSなどクラウドベンダーの「いいとこ取り」を制限。
- 2021年: AWS、対抗してElasticsearchをフォーク。OpenSearch誕生(Apache 2.0ライセンス維持)。
- 2024年: OpenSearchがLinux Foundation傘下に。より中立的なOSSプロジェクトへ。
Elastic社から見れば「自分たちが開発したものをAWSが勝手に商売に使っている」という不満があり、AWSから見れば「オープンソースの精神に反する」という主張。どちらの言い分にも一理ある、業界では有名なドラマです。
機能・性能比較
| 項目 | Elasticsearch | OpenSearch |
|---|---|---|
| ライセンス | SSPL / Elastic License(非OSS) | Apache 2.0(真のOSS) |
| 運営 | Elastic社 | Linux Foundation(AWS主導) |
| パフォーマンス | 40〜140%高速(Elastic社ベンチマーク) | Big5ワークロードで1.6x高速(Trail of Bits調査) |
| AWS統合 | 自前でEC2に構築等 | マネージドサービス完備 |
| 可視化ツール | Kibana | OpenSearch Dashboards |
ベンチマーク結果は計測者やワークロードによって異なります。自身の環境でテストすることをおすすめします。
選び方の指針
OPENSEARCH向き
- AWSメインで使っている
- 真のOSSライセンスが必要(SaaSとして再販等)
- コスト重視でマネージドサービスを使いたい
- ベンダーロックインを避けたい
ELASTICSEARCH向き
- GCP/Azureメイン
- 最新機能・最高パフォーマンスが必要
- Elastic Cloudを使う予算がある
- Elastic社のサポートが欲しい
正直なところ、普通に使う分にはほぼ同じです。インフラ環境とライセンス要件で決めるのが現実的でしょう。
Source: InfoQ - Elastic Changes Licences, Trail of Bits - Benchmarking
用途別の選び方
| 用途 | 最適解 |
|---|---|
| トランザクション、データの整合性 | PostgreSQL |
| 大量テキストの全文検索 | OpenSearch |
| ログ分析・集計 | OpenSearch |
| JOINを減らして高速化したいだけ | RDB内で非正規化/マテビュー |
| ECサイトの商品検索を作りたい | OpenSearch または PGroonga |
| 中小規模の日本語検索 | PGroonga |


まだコメントはありません。最初のコメントを残しませんか?