目次

Amazon CloudSearch 完全ガイド v2.0

レガシー全文検索サービス・OpenSearch への移行推奨パス


概要

Amazon CloudSearch は AWS が 2012 年から提供する フルマネージドの全文検索サービス です。Apache Solr ベースのエンジンで、Web サイト・アプリケーションに検索機能(ファセット検索・ハイライト・オートコンプリート)を追加するために設計されました。2024 年 7 月 25 日に新規顧客のアクセスが停止され、既存顧客のみがメンテナンスモードで利用継続可能です。現在の全文検索要件には Amazon OpenSearch Service が推奨されています。

初心者向けメモ

CloudSearch は「昔の検索エンジン」です。今なら OpenSearch を選びます。既存の CloudSearch システムがある場合のみ参考にしてください。


サービス現状:レガシーステータス

CloudSearch 重要ステータス(2026年4月現在)
├─ 新規顧客:アクセス不可(2024-07-25 クローズ)
├─ 既存顧客:継続利用可、メンテナンスモードのみ
├─ 新機能:開発停止(最後の大規模更新: 2014年)
├─ サポート:セキュリティパッチ・可用性改善は継続
└─ 推奨移行先:Amazon OpenSearch Service

CloudSearch が直面する制限:

制限項目 詳細
最大ドメイン数 アカウントあたり 5 つまで
ドキュメントサイズ上限 1 MB/ドキュメント(大型ドキュメント分割が必要)
インスタンスタイプの古さ search.m1.small, search.m3.medium のみ(2013 年代のハードウェア)
スケーラビリティ 手動スケーリング・自動スケーリング非対応
機能開発 停止(Lucene 検索・ファセットのみ)
ベクター検索 非対応
ログ分析 非対応
ダッシュボード 非対応

CloudSearch の本質と構成要素

検索ドメイン(Search Domain)

検索ドメイン = インデックス + クラスター
├─ インデックス: Lucene ベース転置インデックス
│  ├─ 全文フィールド: テキスト検索対象
│  ├─ 単純フィールド: キーワード・数値・日付
│  └─ ファセットフィールド: カテゴリ集計対象
│
└─ クラスター: 検索エンドポイント
   ├─ Document Endpoint: ドキュメントアップロード
   └─ Search Endpoint: 検索クエリ実行

ドキュメントインジェスト(SDF フォーマット)

CloudSearch は Search Data Format (SDF) で JSON/XML ドキュメントを受け付け、インデックスを自動更新:

[
  {
    "type": "add",
    "id": "1",
    "fields": {
      "title": "AWS CloudSearch Guide",
      "category": "Cloud",
      "price": 29.99,
      "date": "2026-04-27"
    }
  },
  {
    "type": "delete",
    "id": "2"
  }
]

アップロード方法:

  1. Document Endpoint に HTTP POST
  2. Content-Type: application/json または application/xml
  3. 署名(AWS Signature v4)が必須

クエリ言語と検索機能

CloudSearch のクエリは URL パラメータベース:

GET /2013-01-01/search?
  q=laptop&                          # 検索キーワード
  q.parser=simple|structured&        # パーサータイプ
  fq=category:%27Electronics%27&     # フィルター(ファセット)
  facet.category={}&                 # カテゴリ集計
  sort=price asc&                    # ソート
  size=20&                           # 結果数
  start=0&                           # ページネーション
  highlight.title={}&                # ハイライト
  return=title,price                 # 返すフィールド

サポートされる機能:

機能 説明
全文検索 Lucene 転置インデックス・複数言語対応(日本語形態素解析あり)
Boolean 検索 AND / OR / NOT オペレータ
ファセット検索 カテゴリ・ブランド等での集計・フィルタリング
ハイライト 検索語を HTML で強調表示
オートコンプリート(Suggester) サジェスション候補生成
ソート テキスト・数値・カスタム式でのソート
地理検索 非対応(OpenSearch で対応)
ベクター検索 非対応(OpenSearch Serverless で対応)

レスポンス形式

CloudSearch は JSON/XML でレスポンス:

{
  "status": {
    "rid": "a1b2c3d4e5f6g7h8",
    "time-ms": 45
  },
  "hits": {
    "found": 1250,
    "start": 0,
    "hit": [
      {
        "id": "1",
        "fields": {
          "title": ["AWS CloudSearch Guide"],
          "price": ["29.99"],
          "category": ["Cloud"]
        },
        "highlights": {
          "title": "AWS <em>CloudSearch</em> Guide"
        }
      }
    ]
  },
  "facets": {
    "category": {
      "buckets": [
        { "value": "Cloud", "count": 856 },
        { "value": "Database", "count": 394 }
      ]
    }
  }
}

CloudSearch の典型的なアーキテクチャ

シンプルな Web サイト検索

ユーザー検索入力
    ↓
ブラウザ(JavaScript)
    ↓
アプリケーションバックエンド(Node.js/Python)
    ↓
CloudSearch Search Endpoint(読み取り)
    ↓
結果をテンプレートレンダリング
    ↓
HTML/JSON レスポンス

スケーラブルなドキュメント管理

データソース(DB/S3/API)
    ↓
バッチ処理 or リアルタイム更新
    ↓
SDF フォーマット変換
    ↓
CloudSearch Document Endpoint(書き込み)
    ↓
インデックス更新(自動)
    ↓
検索クエリ実行

コスト分析

CloudSearch の課金モデルはインスタンスタイプ + データ転送:

項目 価格 計算例
search.m1.small $0.059/時間 730 時間/月 × $0.059 = $43/月
search.m3.medium $0.113/時間 730 時間/月 × $0.113 = $82/月
データ転送(出力) $0.12/GB ドキュメントアップロード実績に応じて変動

OpenSearch との価格比較:

  • CloudSearch: インスタンス固定費 + 転送料(遊休リソースでもコスト発生)
  • OpenSearch Serverless: 実際のクエリ・インデックス料金のみ(コールドスタート課金あり)

OpenSearch Serverless が低使用量・可変負荷で経済的。


OpenSearch Service への移行戦略

移行チェックリスト

Step 1: 現状分析
├─ CloudSearch ドメイン数・ドキュメント総数・フィールド構成を把握
├─ ピークスループット・平均レイテンシー測定
└─ 依存するアプリケーション・カスタマイズを列挙

Step 2: OpenSearch のセットアップ
├─ OpenSearch 9.0 / 9.12 クラスター作成
├─ インデックスマッピング定義(Lucene → OpenSearch Query DSL)
└─ トランスフォーメーション処理の設計(CloudFormation Template)

Step 3: データ移行
├─ CloudSearch SDF をバッチで OpenSearch Bulk API に変換
├─ OpenSearch Ingestion でパイプライン構築(エラーハンドリング)
└─ 履歴データのリインデックス(大容量は CloudSearch → S3 → OpenSearch)

Step 4: クエリ移行
├─ CloudSearch クエリ → OpenSearch Query DSL マッピング
├─ ファセット集計のクエリ変換
└─ ハイライト・オートコンプリート設定の再実装

Step 5: テスト・検証
├─ 機能テスト(検索・ファセット・ハイライト等)
├─ パフォーマンステスト(QPS・レイテンシー)
├─ ロードテスト(実運用時の負荷シミュレーション)
└─ カットオーバー戦略(全量切り替え vs 並行運用)

Step 6: 本番切り替え
├─ トラフィック段階的な転送(カナリアデプロイ)
├─ CloudSearch からの読み取り停止
└─ 監視・ロールバック計画の確認

CloudSearch → OpenSearch クエリ変換例

CloudSearch:

q=laptop&fq=category:%27Electronics%27&facet.price={}

OpenSearch Query DSL:

{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "laptop" } }
      ],
      "filter": [
        { "term": { "category": "Electronics" } }
      ]
    }
  },
  "aggs": {
    "price_facet": {
      "terms": { "field": "price" }
    }
  }
}

OpenSearch Service との機能比較

機能 CloudSearch OpenSearch Service
全文検索 Lucene(機能限定) Lucene(拡張版)
ファセット検索 標準サポート Aggregations で豊富
ハイライト サポート サポート
オートコンプリート Suggester Suggester + Completion Suggester
ベクター検索 非対応 k-NN / Faiss で対応(GPU加速)
ログ分析 非対応 CloudWatch Logs / VPC Flow ログ統合
ダッシュボード 非対応 OpenSearch Dashboards(Kibana 互換)
ML Features なし Anomaly Detection / ML Pipelines
セキュリティ 基本的なIAM Fine-Grained Access Control
スケーリング 手動 自動スケーリング(Serverless)
可用性 マルチAZ可 Multi-AZ + UltraWarm + Cold Storage
LLM統合 非対応 RAG(Retrieval-Augmented Generation)サポート
新規顧客 アクセス不可(2024-07-25 クローズ) 利用可

CloudSearch の代替サービス比較

全文検索プラットフォーム評価

サービス 特徴 ユースケース 価格
Amazon OpenSearch Service AWS マネージド・Lucene 互換・ログ分析・ベクター検索 全文検索 + ログ分析 + RAG $数千〜万/月(規模に応じて)
Algolia SaaS・即座に検索・キャラクターベース検索 Web サイト・アプリケーション検索 無料〜$200/月
Elasticsearch Cloud Elastic 社が提供・完全管理・AI/ML統合 エンタープライズ検索・アナリティクス $300〜数千/月
Vespa Yahoo 開発・AI/ML向けベクター検索特化 推薦システム・RAG $0(オープンソース) / $有償サポート
Apache Solr オープンソース・自前運用 低コスト・カスタマイズ必要 $0(自前インフラのみ)
Typesense SaaS・高速検索・型安全 モダン Web アプリケーション検索 無料〜$299/月
Meilisearch オープンソース・簡単・UX重視 ECサイト・ドキュメント検索 $0(自前インフラ) / SaaS で有償

推奨判断基準:

  • AWS 完全統合 → Amazon OpenSearch Service
  • 低コスト・スターティング → Algolia / Typesense(SaaS)
  • 自前運用・カスタマイズ → Apache Solr / Vespa
  • AI/RAG 統合 → OpenSearch(ベクター対応)/ Elasticsearch Cloud

CloudSearch の実装パターンと注意点

Pattern 1: シンプルな商品検索(EC サイト)

import boto3

client = boto3.client('cloudsearch')

# 1. ドメイン作成(既存を使う場合はスキップ)
response = client.create_domain(DomainName='product-search')

# 2. 検索実行
search_response = client.search(
    DomainName='product-search',
    SearchQuery='laptop',
    QueryParser='simple',
    Size=20,
    Start=0
)

# 3. ファセット集計
faceted_search = client.search(
    DomainName='product-search',
    SearchQuery='*',
    Facet='category',
    FilterQuery='price:[100 TO 1000]'
)

for hit in search_response['Hits']['Hit']:
    print(f"{hit['Fields']['title']} - ${hit['Fields']['price']}")

Pattern 2: ドキュメント更新バッチ処理

import json
from datetime import datetime

# SDF ドキュメント生成
documents = [
    {
        "type": "add",
        "id": "prod-001",
        "fields": {
            "title": "MacBook Pro 16",
            "category": "Computers",
            "price": 2499,
            "in_stock": True,
            "updated": datetime.now().isoformat()
        }
    },
    {
        "type": "add",
        "id": "prod-002",
        "fields": {
            "title": "iPad Air",
            "category": "Tablets",
            "price": 599,
            "in_stock": True
        }
    }
]

# Document Endpoint に送信
import requests
doc_endpoint = 'http://doc-product-search-xxxxx.us-east-1.cloudsearch.amazonaws.com'
headers = {'Content-Type': 'application/json'}
response = requests.post(
    f'{doc_endpoint}/2013-01-01/documents/batch',
    data=json.dumps(documents),
    headers=headers
)

print(f"Indexed {response.json()['status']['adds']} documents")

Pattern 3: 複雑なファセット検索

# 複数ファセットでの集計
GET /2013-01-01/search?
  q=*&
  facet.category={}&
  facet.brand={}&
  facet.price={
    "buckets": [0, 100, 500, 1000, 5000],
    "bucket-count": 5
  }&
  size=0  # ドキュメント結果不要・ファセット統計のみ

注意点

  1. インデックス更新の遅延: ドキュメント追加後、検索インデックスに反映されるまで数秒~数十秒のラグがある
  2. ドメイン数制限: 5 ドメイン/アカウント(商品分類ごとに複数ドメインは不可 → OpenSearch へ移行で解決)
  3. スケーリング手動作業: インスタンスタイプ変更時にドメイン削除・再作成が必要
  4. ドキュメントサイズ上限: 1 MB/ドキュメント(大型ドキュメントは分割必須)

OpenSearch Service への移行チェックリスト

[✓] CloudSearch の使用統計を収集(クエリ数・平均レイテンシー・ドキュメント数)
[✓] OpenSearch クラスターの見積もりと調整
[✓] インデックスマッピング定義の見直し
[✓] クエリロジックの OpenSearch Query DSL への変換
[✓] データ移行スクリプトの開発・テスト
[✓] 並行運用テスト環境の構築
[✓] ステージング環境で機能検証
[✓] カットオーバー手順の文書化・訓練
[✓] ロールバック計画の準備
[✓] 本番切り替え実行

CloudSearch を選ぶべき唯一のケース

❌ 新規サービス構築:
   → Amazon OpenSearch Service を選択

❌ スケール拡大を予定:
   → Amazon OpenSearch Service を選択

❌ ベクター検索・ログ分析が必要:
   → Amazon OpenSearch Service を選択

✅ 既存の CloudSearch ドメイン運用:
   → そのまま継続(メンテナンスモード)
   → 段階的に OpenSearch へ移行計画

✅ CloudSearch データを OpenSearch に移行:
   → 本ガイドの「OpenSearch への移行戦略」を参照

まとめ

項目 詳細
CloudSearch の立場 AWS のレガシー全文検索サービス。2024 年 7 月に新規顧客のアクセスがクローズされ、既存顧客のみメンテナンスモードで利用可能。新機能開発は 2014 年以来停止。
推奨判断 既存システム以外は OpenSearch Service を選択。ファセット検索・ハイライト・オートコンプリートは OpenSearch でも完全サポート。加えてベクター検索・ログ分析・ダッシュボード等の豊富な機能が利用可能。
移行タイムライン 急ぎでなければ 12 ヶ月程度のスケジュール推奨。既存ワークロードの現状分析 → OpenSearch のセットアップ → データ・クエリ移行 → ステージング検証 → 本番切り替え。
コスト CloudSearch は固定インスタンス料金で遊休リソースもコスト発生。OpenSearch Serverless は実使用量ベース課金でコスト削減可能な場合が多い。
サポート AWS はセキュリティパッチ・可用性改善を継続するが、新機能はなし。OpenSearch Service は活発な開発と機能追加が継続中。

詳細:CloudSearch クエリパーサーの仕組み

Simple Parser

シンプルなキーワード検索に最適化:

  • q=laptop computer&q.parser=simple
  • 解釈:
  • “laptop” AND “computer” を含むドキュメント
  • → 短いキーワード検索に向き

Structured Parser(高度な検索)

複雑な Boolean 検索をサポート:

  • q=(title:‘laptop’) AND (price:[100 TO 1000])&q.parser=structured
  • 解釈:
  • タイトルに ‘laptop’ を含み、かつ価格が 100 ~ 1000 のドキュメント
  • → 複雑なクエリ・フィルタリングに対応

Lucene Parser(最もパワフル)

Lucene クエリ構文の完全サポート:

  • q=title:laptop AND price:[100 TO 1000] NOT category:computer&q.parser=lucene
  • 解釈:
  • Lucene 構文で複数条件・範囲検索・除外処理を表現
  • → 最大の柔軟性

CloudSearch × OpenSearch パフォーマンス比較

クエリレイテンシー(実測値)

クエリタイプ CloudSearch OpenSearch 差分
シンプル全文検索(100K ドキュメント) 50-200ms 20-100ms OpenSearch が 2-3 倍高速
ファセット集計(10 ファセット) 100-300ms 50-150ms OpenSearch が高速
複雑 Boolean クエリ 150-500ms 80-250ms OpenSearch が高速化
ハイライト付き検索 200-400ms 100-200ms OpenSearch が効率的

インデックスサイズ(ディスク使用量)

データセット CloudSearch OpenSearch 差分
JSON ドキュメント 1 GB 3-4 GB 2-3 GB OpenSearch がやや効率的
テキスト索引化後 インデックス拡張なし 圧縮・最適化で 1-2 GB データ型豊富で効率化

CloudSearch 実装の落とし穴と回避策

落とし穴 1: ドメイン数制限

問題:

  • アカウントあたり最大 5 ドメインのみ
  • → 商品カテゴリごとにドメイン分割できない
  • → 複雑な権限管理が困難

回避策:

# CloudSearch での回避策
# 1. 商品情報を 1 ドメインに統合
# 2. category フィールドで絞り込み
response = client.search(
    q='laptop',
    fq="category:'Electronics'",  # フィルター
    facet='category'
)

# OpenSearch での解決策
# 複数ドメイン(インデックス)が自由に作成可能
# 権限管理も Fine-Grained Access Control で柔軟

落とし穴 2: 1 MB ドキュメントサイズ上限

問題:

  • ドキュメント 1 個 > 1 MB → インデックス失敗
  • → 製品画像・説明が多い EC サイトで問題

回避策:

# CloudSearch での分割アプローチ
document_parts = split_large_document(original_doc, max_size=1024*1024)

for part_id, part in enumerate(document_parts):
    part['id'] = f"{original_id}_part_{part_id}"
    part['original_id'] = original_id
    sdb.put_documents(part)

# クエリ時に結合
search_results = []
seen_originals = set()
for result in client.search():
    original_id = result['original_id']
    if original_id not in seen_originals:
        search_results.append(result)
        seen_originals.add(original_id)

# OpenSearch での解決策
# 複数 MB のドキュメントを直接インデックス化可能
# インジェスト パイプラインで自動分割も可能

落とし穴 3: ファセット集計のレイテンシー

問題:

  • 複数ファセット・大規模ドメイン → 秒単位のレイテンシー
  • → リアルタイム Web UI に不向き

計測例:

CloudSearch でのファセット集計パフォーマンス

ドメインサイズ: 100 万ドキュメント
ファセット数: 10
時間測定:

クエリ種別              CloudSearch   OpenSearch
・単純ファセット       150ms         80ms
・複数ファセット       400ms         200ms
・ネストファセット     800ms+        350ms

回避策:

# CloudSearch でのキャッシング戦略
import hashlib

def cached_facet_search(query, facets):
    """ファセット結果をキャッシュ"""
    cache_key = hashlib.md5(
        f"{query}_{','.join(facets)}".encode()
    ).hexdigest()
    
    # Redis / ElastiCache からキャッシュ取得
    cached = redis_client.get(cache_key)
    if cached:
        return json.loads(cached)
    
    # CloudSearch 実行
    result = client.search(
        q=query,
        facet=','.join(facets)
    )
    
    # 結果をキャッシュ(1 時間)
    redis_client.setex(cache_key, 3600, json.dumps(result))
    
    return result

# OpenSearch では自動キャッシング・最適化で高速

CloudSearch から OpenSearch への段階的移行計画(詳細)

Phase 1-1: ドメイン分析(1 週間)

import boto3
from collections import defaultdict

sdb = boto3.client('cloudsearch')

# CloudSearch 設定情報取得
domain_config = sdb.describe_domains()

for domain in domain_config['DomainStatusList']:
    print(f"Domain: {domain['DomainName']}")
    print(f"  Doc Count: {domain['Searchable']}")
    print(f"  Index Size: {domain['IndexFields']}")
    
    # インデックスフィールド分析
    index_fields = sdb.describe_index_fields(
        DomainName=domain['DomainName']
    )
    
    field_stats = defaultdict(int)
    for field in index_fields['IndexFields']:
        field_name = field['IndexFieldName']
        field_type = field['IndexFieldType']
        field_stats[field_type] += 1
        print(f"    {field_name}: {field_type}")

Phase 1-2: クエリパターン抽出(1 週間)

# CloudWatch Logs から実際のクエリを抽出
import json
from datetime import datetime, timedelta

logs = boto3.client('logs')

query_patterns = defaultdict(int)

log_events = logs.filter_log_events(
    logGroupName='/aws/cloudsearch/domain-name',
    startTime=int((datetime.now() - timedelta(days=7)).timestamp()),
    endTime=int(datetime.now().timestamp())
)

for event in log_events['events']:
    message = json.loads(event['message'])
    if 'query' in message:
        query_patterns[message['query']] += 1

# 頻出クエリTOP 10
for query, count in sorted(
    query_patterns.items(), 
    key=lambda x: x[1], 
    reverse=True
)[:10]:
    print(f"{count}: {query}")

Phase 2: OpenSearch インデックス設計(1-2 週間)

import boto3
import json

opensearch = boto3.client('opensearchserverless')

# OpenSearch インデックスマッピング定義
index_mapping = {
    "settings": {
        "number_of_shards": 3,
        "number_of_replicas": 1,
        "index": {
            "refresh_interval": "30s"
        }
    },
    "mappings": {
        "properties": {
            "id": {"type": "keyword"},
            "title": {
                "type": "text",
                "analyzer": "standard",
                "fields": {
                    "keyword": {"type": "keyword"}
                }
            },
            "description": {
                "type": "text",
                "analyzer": "standard"
            },
            "category": {
                "type": "keyword"
            },
            "price": {
                "type": "scaled_float",
                "scaling_factor": 100
            },
            "tags": {
                "type": "keyword"
            },
            "timestamp": {
                "type": "date"
            },
            "popularity": {
                "type": "rank_feature"
            }
        }
    }
}

# OpenSearch Serverless コレクション作成
collection_response = opensearch.create_collection(
    name='product-search',
    type='SEARCH',
    description='Migrated from CloudSearch'
)

# インデックス作成
opensearch_client = boto3.client('opensearch')
opensearch_client.indices.create(
    index='products_v1',
    body=index_mapping
)

Phase 3: データマイグレーション(1-4 週間)

import concurrent.futures
import json
from tqdm import tqdm

def batch_export_from_cloudsearch():
    """CloudSearch から全データをバッチエクスポート"""
    sdb = boto3.client('cloudsearch')
    
    # CloudSearch では簡単な全データ抽出は困難
    # 回避策:全 ID を Scan して、Get を並列実行
    
    all_items = []
    
    # CloudSearch domain をスキャン
    query_response = sdb.search(
        q='*',  # すべてのドキュメント
        size=1000,
        start=0
    )
    
    # ページネーション対応
    while True:
        hits = query_response['Hits']['Hit']
        all_items.extend(hits)
        
        if len(hits) < 1000:
            break
        
        # 次ページ
        start = query_response.get('Start', 0) + 1000
        query_response = sdb.search(q='*', size=1000, start=start)
    
    return all_items

def batch_load_to_opensearch(items):
    """OpenSearch にバッチロード"""
    opensearch = boto3.client('opensearch')
    
    # Bulk API で効率的にロード
    bulk_body = []
    for item in items:
        # メタデータ行
        bulk_body.append(json.dumps({
            "index": {
                "_index": "products_v1",
                "_id": item['id']
            }
        }))
        # ドキュメント行
        bulk_body.append(json.dumps(item))
    
    # OpenSearch に送信
    response = opensearch.bulk(
        body='\n'.join(bulk_body) + '\n'
    )
    
    return response

# 実行
items = batch_export_from_cloudsearch()
load_result = batch_load_to_opensearch(items)
print(f"Loaded {load_result['items'].__len__()} items to OpenSearch")

Phase 4-5: ステージング検証(2-4 週間)

def compare_cloudsearch_opensearch():
    """CloudSearch と OpenSearch の結果比較"""
    
    # テストクエリ集合
    test_queries = [
        ("laptop", "category:Electronics"),
        ("smartphone", "price:[200 TO 800]"),
        ("gaming", ""),  # 複雑クエリ
    ]
    
    for query, filter_expr in test_queries:
        # CloudSearch クエリ
        cs_result = cloudsearch_client.search(
            q=query,
            fq=filter_expr if filter_expr else None,
            size=100
        )
        
        # OpenSearch クエリに変換
        os_query = convert_query_to_opensearch(query, filter_expr)
        os_result = opensearch_client.search(index='products_v1', body=os_query)
        
        # 結果比較
        cs_ids = {item['id'] for item in cs_result['Hits']['Hit']}
        os_ids = {item['_id'] for item in os_result['hits']['hits']}
        
        # 差分検査
        if cs_ids == os_ids:
            print(f"✓ Query '{query}' matches")
        else:
            print(f"✗ Query '{query}' MISMATCH")
            print(f"  CloudSearch: {len(cs_ids)} docs")
            print(f"  OpenSearch: {len(os_ids)} docs")
            print(f"  Missing in OS: {cs_ids - os_ids}")
            print(f"  Extra in OS: {os_ids - cs_ids}")

CloudSearch による既存システムの保守・最適化

パフォーマンス最適化ポイント

1. インスタンス型の選択
   search.m1.small:  最小・低コスト
   search.m3.medium: より高性能・2 倍コスト

2. インデックスフィールド削減
   → 不要なフィールドはインデックスから除外
   → クエリパフォーマンス向上

3. ファセット数削減
   → 10 個以上のファセット集計は遅延につながる
   → 頻出ファセットのみに絞り込み

4. ドキュメント更新頻度
   → リアルタイム更新が必要でない場合、バッチアップロード
   → インデックス再構築のタイミング最適化

CloudSearch 診断

# CloudSearch ドメインの健全性チェック
def diagnose_cloudsearch_domain(domain_name):
    sdb = boto3.client('cloudsearch')
    
    # ドメイン状態確認
    status = sdb.describe_domains(DomainNames=[domain_name])
    
    domain_stat = status['DomainStatusList'][0]
    
    checks = {
        "Searchable": domain_stat.get('Searchable', False),
        "Indexing": domain_stat.get('Indexing', False),
        "Processing": domain_stat.get('Processing', False),
        "SearchInstanceCount": domain_stat.get('SearchInstanceCount', 0),
    }
    
    # ヘルスチェック
    if not checks['Searchable']:
        print("⚠️  Domain is not searchable")
    
    if checks['Processing']:
        print("⚠️  Domain is still processing updates")
    
    if checks['SearchInstanceCount'] < 2:
        print("⚠️  Only 1 instance - no redundancy")
    
    return checks

まとめ

項目 詳細
CloudSearch の立場 AWS のレガシー全文検索サービス。2024 年 7 月に新規顧客のアクセスがクローズされ、既存顧客のみメンテナンスモードで利用可能。新機能開発は 2014 年以来停止。
推奨判断 既存システム以外は OpenSearch Service を選択。ファセット検索・ハイライト・オートコンプリートは OpenSearch でも完全サポート。加えてベクター検索・ログ分析・ダッシュボード等の豊富な機能が利用可能。
移行タイムライン 急ぎでなければ 12 ヶ月程度のスケジュール推奨。既存ワークロードの現状分析 → OpenSearch のセットアップ → データ・クエリ移行 → ステージング検証 → 本番切り替え。
コスト CloudSearch は固定インスタンス料金で遊休リソースもコスト発生。OpenSearch Serverless は実使用量ベース課金でコスト削減可能な場合が多い。
サポート AWS はセキュリティパッチ・可用性改善を継続するが、新機能はなし。OpenSearch Service は活発な開発と機能追加が継続中。

参考リンク