<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Ugo Sangiorgi - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Ugo Sangiorgi - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/kr/search-labs/author/ugo-sangiorgi</link>
    </image>
    <link>https://www.elastic.co/kr/search-labs/author/ugo-sangiorgi</link>
    <atom:link href="https://www.elastic.co/kr/search-labs/rss/author/ugo-sangiorgi.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[kr]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 04:16:12 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Elasticsearch BBQ와 OpenSearch FAISS: 벡터 검색 성능 비교]]></title>
    <description><![CDATA[Elasticsearch BBQ와 OpenSearch FAISS의 성능 비교.]]></description>
    <content:encoded><![CDATA[<p><strong>이진 양자화를 통한 벡터 검색: BBQ가 포함된 Elasticsearch는 FAISS가 포함된 OpenSearch보다 5배 빠릅니다</strong>. Elastic은 특히 시맨틱 검색/벡터 검색 영역에서 Elasticsearch와 OpenSearch 간의 성능 차이를 명확히 해달라는 커뮤니티의 요청을 받았기 때문에 명확한 데이터 기반 비교를 제공하기 위해 이러한 성능 테스트를 수행했습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta8792b5284e7a553/6a1709b9961e69a084c4cee6/7f4f8d08f7bee188423e4e65f0caefc7e34f0355-1600x681.png" alt="Elasticsearch BBQ와 OpenSearch FAISS - 속도 &amp; 처리량 리콜 비교" /><h2>이진 양자화 대결</h2><p>고차원 벡터를 원래 형태로 저장하는 것은 메모리 집약적일 수 있습니다. 양자화 기술은 이러한 벡터를 콤팩트한 표현으로 압축하여 메모리 사용량을 대폭 줄여줍니다. 그러면 검색이 압축된 공간에서 작동하므로 계산 복잡성이 줄어들고 특히 대규모 데이터 세트에서 검색 속도가 빨라집니다.</p><p>Elastic은 Lucene을 최고 성능의 벡터 엔진으로 만들기 위해 최선을 다하고 있습니다. 우리는 Lucene을 기반으로 Elasticsearch 8.16에서 <a href="https://www.elastic.co/kr/search-labs/blog/better-binary-quantization-lucene-elasticsearch">더 나은 이진 정량화</a> (BBQ)를 도입했고 8.18과 9.0에서 이를 더욱 발전시켰습니다. BBQ는 플로트32 차원을 비트로 축소하는 새로운 <a href="https://www.elastic.co/kr/search-labs/blog/optimized-scalar-quantization-elasticsearch">스칼라 양자화</a> 방식을 기반으로 구축되어 높은 순위 품질을 유지하면서 최대 95%의% 메모리 절감 효과를 제공합니다.</p><p>반면 OpenSearch는 여러 벡터 엔진, 즉 nmslib(현재는 더 이상 사용되지 않음), Lucene 및 FAISS를 사용합니다. <a href="https://www.elastic.co/kr/search-labs/blog/elasticsearch-opensearch-vector-search-performance-comparison">이전 블로그에서</a> 벡터 검색을 위해 Elasticsearch와 OpenSearch를 비교한 적이 있습니다. 세 가지 데이터 세트를 사용하여 두 제품에서 서로 다른 엔진 및 구성 조합을 테스트했습니다.</p><p>이 블로그에서는 현재 두 제품에서 사용할 수 있는 이진 양자화 알고리즘에 초점을 맞춥니다. <a href="https://github.com/elastic/rally-tracks/edit/master/openai_vector">openai_vector</a> Rally 트랙을 사용하여 BBQ와 함께 Elasticsearch를 테스트하고 <a href="https://opensearch.org/docs/latest/search-plugins/knn/knn-vector-quantization/#binary-quantization">FAISS의 이진 정량화를 통해 OpenSearch를 테스트했습니다.</a></p><p>주요 목표는 동일한 리콜 수준에서 두 솔루션의 성능을 평가하는 것이었습니다. <em>리콜이란</em> 무엇을 의미하나요? 리콜은 검색 시스템에서 얼마나 많은 관련 결과를 성공적으로 검색했는지를 측정하는 지표입니다.</p><p>이 평가에서는 recall@k가 특히 중요한데, 여기서 <em>k는</em> 고려되는 상위 결과의 수를 나타냅니다. 따라서 <strong>리콜@10</strong>, <strong>리콜@50 및 리콜@100은</strong> 각각 검색된 상위 10개, 50개 및 100개의 항목에서 얼마나 많은 실제 관련성 있는 결과가 나타나는지 측정합니다. 리콜은 0에서 1(또는 0% ~ 100% 정밀도)의 척도로 표시됩니다. 이는 리콜이 항상 1(100%)인 정확한 KNN이 아닌 근사 KNN(ANN)에 대해 이야기하고 있기 때문에 중요합니다.</p><p><em>k의</em> 각 값에 대해 최종 순위를 적용하기 전에 고려되는 후보의 수인 <em>n도 </em>지정했습니다. 즉, Recall@10, Recall@50 및 Recall@100의 경우 시스템은 먼저 이진 양자화 알고리즘을 사용하여 <em>n개의</em> 후보를 검색한 다음 상위 <em>k개의</em> 결과에 예상되는 관련 항목이 포함되어 있는지 여부를 판단하기 위해 순위를 매깁니다.</p><p><em>n을</em> 제어함으로써 효율성과 정확성 사이의 균형을 분석할 수 있습니다. 일반적으로 <em>n이</em> 높을수록 순위를 매길 수 있는 후보가 많아져 리콜률이 <strong>높아지지만</strong> 지연 시간이 <strong>길어지고</strong> 처리량도<strong> 감소합니다 </strong>. 반대로 <em>n이</em> 낮을수록 검색 속도가 빨라지지만 초기 세트에 관련 후보가 너무 적게 포함될 경우 검색 회수율이 떨어질 수 있습니다.</p><p>이 비교에서 Elasticsearch는 동일한 설정에서 OpenSearch보다 더 낮은 지연 시간과 더 높은 처리량을 보여주었습니다.</p><h2>방법론</h2><p>전체 구성과 함께 Terraform 스크립트, Kubernetes 매니페스트 및 특정 Rally 트랙은 이 <a href="https://github.com/elastic/elasticsearch-opensearch-vector-performance/tree/bbq">리포지토리에서</a> <a href="https://github.com/elastic/elasticsearch-opensearch-vector-performance/tree/bbq/rally-custom/custom_tracks/elasticsearch/openai_vector_bq"><em>openai_vector_bq</em></a> 아래에서 확인할 수 있습니다.</p><p>이전 벤치마크와 마찬가지로 다음과 같이 구성된 Kubernetes 클러스터를 사용했습니다:</p><ul><li><p>3개의 <code>e2-standard-32</code> 시스템(128GB RAM 및 32 CPU)을 갖춘 Elasticsearch 9.0용 노드 풀 1개</p></li><li><p>OpenSearch 2.19용 노드 풀 1개, <code>e2-standard-32</code> 머신 3대(128GB RAM 및 32개 CPU)</p></li><li><p>2개의 <code>e2-standard-4</code> 머신(16GB RAM 및 4개의 CPU)이 있는 Rally용 노드 풀 1개</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt934e988e96a5849f/6a1709bbacf08838f9be9ac1/169bb6033f6eebfd1b177b3446bf916fde4ee5c5-1600x856.png" alt="Elasticsearch BBQ와 Opensearch FAISS 방법론 설정" /><p>하나의 Elasticsearch 클러스터 버전 9.0과 하나의 OpenSearch 클러스터 버전 2.19를 설정했습니다.</p><p>Elasticsearch와 OpenSearch 모두 정확히 동일한 설정으로 테스트했습니다. OpenAI의 텍스트 임베딩-ada-002 <a href="https://openai.com/blog/new-and-improved-embedding-model">모델을 사용해 생성된</a> <a href="https://huggingface.co/datasets/BeIR/nq">임베딩으로 강화된 NQ 데이터 세트의</a> 250만 개의 문서를 사용하는 <a href="https://github.com/elastic/rally-tracks/edit/master/openai_vector">openai_vector</a> Rally 트랙을 <a href="https://github.com/elastic/elasticsearch-opensearch-vector-performance/commit/b97d5d95c22c8cf862f2030964524bdd156a5da3">일부 수정하여 사용했습니다.</a></p>{
  "source-file": "open_ai_corpus-initial-indexing.json.bz2",
  "document-count": 2580961,
  "compressed-bytes": 32076749416,
  "uncompressed-bytes": 90263571686
}<p>검색 작업을 수행하기 위해 8개의 동시 클라이언트를 사용하여 다양한 리콜 수준(리콜@10, 리콜@50, 리콜@100)에서 측정된 지연 시간 및 처리량에 대한 결과 보고서입니다. 복제본 없이 단일 샤드를 사용했습니다.</p><p>다음과 같은 k-n-점수 조합을 실행했습니다. 10-2000-2000 또는 <em>k:10</em>, <em>n:2000</em> 및 <em>rescore:2000</em> 은 2000개의 결과에 대해 재점수('과대 표본 계수' 1에 해당)를 적용하여 n개의 후보(2000개) 중 상위 k(10개)를 검색합니다. 각 검색은 워밍업으로 1000회의 검색으로 10.000회 실행되었습니다:</p><p></p><p><u><strong>Recall@10</strong></u></p><ul><li><p>10-40-40</p></li><li><p>10-50-50</p></li><li><p>10-100-100</p></li><li><p>10-200-200</p></li><li><p>10-500-500</p></li><li><p>10-750-750</p></li><li><p>10-1000-1000</p></li><li><p>10-1500-1500</p></li><li><p>10-2000-2000</p></li></ul><p><u><strong>Recall@50</strong></u></p><ul><li><p>50-150-150</p></li><li><p>50-200-200</p></li><li><p>50-250-250</p></li><li><p>50-500-500</p></li><li><p>50-750-750</p></li><li><p>50-1000-1000</p></li><li><p>50-1200-1200</p></li><li><p>50-1500-1500</p></li><li><p>50-2000-2000</p></li></ul><p><u><strong>Recall@100</strong></u></p><ul><li><p>100-200-200</p></li><li><p>100-250-250</p></li><li><p>100-300-300</p></li><li><p>100-500-500</p></li><li><p>100-750-750</p></li><li><p>100-1000-1000</p></li><li><p>100-1200-1200</p></li><li><p>100-1500-1500</p></li><li><p>100-2000-2000</p></li></ul><p>벤치마크를 복제하기 위해, rally-elasticsearch와 rally-opensearch 모두에 대한 Kubernetes 매니페스트에는 모든 관련 변수가 컨피그맵에 외부화되어 있으며, <a href="https://github.com/elastic/elasticsearch-opensearch-vector-performance/blob/bbq/k8s/rally-openai_vector-es-bq.yml">여기</a> (ES)와 <a href="https://github.com/elastic/elasticsearch-opensearch-vector-performance/blob/bbq/k8s/rally-openai_vector-os-bq.yml">여기</a> (OS)에서 확인할 수 있습니다. <em>search_ops</em> 매개변수는 k, n, rescore의 모든 조합을 테스트하도록 사용자 지정할 수 있습니다.</p><h3>OpenSearch Rally 구성</h3><p><code>/k8s/rally-openai_vector-os-bq.yml</code></p>apiVersion: v1
kind: ConfigMap
metadata:
  name: rally-params-os
  labels:
    app: rally-opensearch
data:
  user-tags.json: |
    {
      "product": "OpenSearch",
      "product-version": "OpenSearch-2.19.0",
      "product-label": "OpenSearch-2.19-faiss",
      "benchmark-run": "19-feb-recall@100"
    }
  track-params.json: |
    {
      "mapping_type": "vectors-only-mapping-with-docid",
      "standalone_search_clients": 8,
      "standalone_search_iterations": 5000,
      "ann_threshold": 0,
      "vector_mode": "on_disk",
      "compression_level": "32x",
      "vector_method_name": "hnsw",
      "vector_method_engine": "faiss",
      "search_ops": [
        [100, 200, 200],
        [100, 250, 250],
        [100, 300, 300],
        [100, 500, 500],
        [100, 750, 750],
        [100, 1000, 1000],
        [100, 1200, 1200],
        [100, 1500, 1500],
        [100, 2000, 2000]
      ]
    }<h3>검색 인덱스 구성</h3><p>그런 다음 컨피그맵의 변수가 인덱스 구성에 사용되며, 일부 매개변수는 변경되지 않은 상태로 유지됩니다. OpenSearch의 1비트 양자화는 <a href="https://opensearch.org/docs/latest/search-plugins/knn/knn-vector-quantization/#binary-quantization">압축 수준을 "32배"로 설정하여 구성</a>합니다.</p><p><code>index-vectors-only-mapping-with-docid-mapping.json</code></p>{
  "settings": {
    {% if preload_pagecache %}
    "index.store.preload": [
      "vec", "vex", "vem", "veq", "veqm", "veb", "vebm"
    ],
    {% endif %}
    "index.number_of_shards": {{ number_of_shards | default(1) }},
    "index.number_of_replicas": {{ number_of_replicas | default(0) }},
    "index.knn": true,
    "index.knn.advanced.approximate_threshold": {{ ann_threshold | default(15000) }}
  },
  "mappings": {
    "dynamic": false,
    "properties": {
      "docid": {
        "type": "keyword"
      },
      "emb": {
        "type": "knn_vector",
        "dimension": 1536,
        "space_type": "innerproduct",
        "data_type": "float",
        "mode": {{ vector_mode | default("in_memory") | tojson }},
        "compression_level": {{ compression_level | default("32x") | tojson }},
        "method": {
          "name": {{ vector_method_name | default("hnsw") | tojson }},
          "engine": {{ vector_method_engine | default("faiss") | tojson }},
          "parameters": {
            "ef_construction": 100,
            "m": 16
          }
        }
      }
    }
  }
}<h3>Elasticsearch Rally 구성</h3><p><code>/k8s/rally-openai_vector-es-bq.yml</code></p>apiVersion: v1
kind: ConfigMap
metadata:
  name: rally-params-es
  labels:
    app: rally-elasticsearch
data:
  user-tags.json: |
    {
      "product": "Elasticsearch",
      "product-version": "Elasticsearch-9.0.0-ade01164",
      "product-label": "Elasticsearch-9.0-BBQ",
      "benchmark-run": "19-feb-recall@100"
    }
  track-params.json: |
    {
      "mapping_type": "vectors-only-mapping-with-docid",
      "standalone_search_clients": 8,
      "standalone_search_iterations": 5000,
      "vector_index_type": "bbq_hnsw",
      "search_ops": [
        [100, 200, 200],
        [100, 250, 250],
        [100, 300, 300],
        [100, 500, 500],
        [100, 750, 750],
        [100, 1000, 1000],
        [100, 1200, 1200],
        [100, 1500, 1500],
        [100, 2000, 2000]
      ]
    }<h3>Elasticsearch 인덱스 구성</h3><p><code>index-vectors-only-mapping-with-docid-mapping.json</code></p>{
  "settings": {
    {# non-serverless-index-settings-marker-start #}
    {%- if build_flavor != "serverless" or serverless_operator == true -%}
    {% if preload_pagecache %}
    "index.store.preload": [ "vec", "vex", "vem", "veq", "veqm", "veb", "vebm" ],
    {% endif %}
    "index.number_of_shards": {{ number_of_shards | default(1) }},
    "index.number_of_replicas": {{ number_of_replicas | default(0) }}
    {%- endif -%}
    {# non-serverless-index-settings-marker-end #}
  },
  "mappings": {
    "dynamic": false,
    "properties": {
      "docid": {
        "type": "keyword"
      },
      "emb": {
        "type": "dense_vector",
        "element_type": "float",
        "dims": 1536,
        "index": true,
        "similarity": "dot_product",
        "index_options": {
          "type": {{ vector_index_type | default("bbq_hnsw") | tojson }},
          "ef_construction": 100,
          "m": 16
        }
      }
    }
  }
}<h2>결과</h2><p>결과를 해석하는 방법에는 여러 가지가 있습니다. 지연 시간과 처리량 모두에 대해 각 리콜 수준에 따라 단순화된 차트와 상세한 차트를 표시했습니다. 각 지표에 대해 "높을수록 좋다"고 생각하면 차이를 쉽게 알 수 있습니다. 그러나 지연 시간은 음수(낮을수록 좋음)인 반면 처리량은 양수입니다. 단순화된 차트에서는 <strong>(리콜/레이턴시) * 10000 </strong>(간단히 '속도'라고 함)과<strong> 리콜 * 처리량을</strong> 사용했으므로 두 지표 모두 속도가 빠르고 처리량이 많을수록 더 좋다는 의미입니다. 시작해 보겠습니다.</p><h3>리콜 @ 10 - 단순화</h3><p>이 수준의 리콜에서 Elasticsearch BBQ는 OpenSearch FAISS보다 최대 <strong>5배 </strong>(평균 3.9배) 빠르며 평균 <strong>3.2배 더 많은 처리량을</strong> 제공합니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3de6b3460127a8ae/6a1709bcb339d55975769f6f/d580ad53e8974bd3aa75957c413a0136c4e465c5-1600x681.png" alt="Elasticsearch BBQ는 최대 5배(평균 3.9배) 빠르며, 속도와 처리량 Recall@10에서 OpenSearch FAISS보다 평균 3.2배 더 많은 처리량을 제공합니다." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd47045013cac5e9d/6a1709be0e2e49599a41a088/18edce667fe36ab95033264ef8df6f352dda2425-2044x866.png" alt="Elasticsearch BBQ는 OpenSearch FAISS보다 최대 5배(평균 3.9배) 빠르며 평균 3.2배 더 많은 처리량을 제공합니다." /><h4>리콜 @ 10 - 상세</h4><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0ecb02d4a2967dbd/6a1709bf14b270c04fe3c5c6/a7459b87e679f4ad963d0e2f1685499b40f6f050-1600x799.png" alt="자세한 리콜@10 지연 시간 비교 Elasticsearch BBQ와 Opensearch FAISS" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt182da309ad6cfd39/6a1709c166c4f99077f8bfd8/c6036f55a13377654d296eb3148c7199e1965475-1600x799.png" alt="자세한 recall@10 처리량 비교 Elasticsearch BBQ와 Opensearch FAISS." /><p></p><p>작업</p><p>latency.mean</p><p>throughput.mean</p><p>avg_recall</p><p>Elasticsearch-9.0-BBQ</p><p>10-100-100</p><p>11.70</p><p>513.58</p><p>0.89</p><p>Elasticsearch-9.0-BBQ</p><p>10-1000-100</p><p>27.33</p><p>250.55</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>10-1500-1500</p><p>35.93</p><p>197.26</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>10-200-200</p><p>13.33</p><p>456.16</p><p>0.92</p><p>Elasticsearch-9.0-BBQ</p><p>10-2000-2000</p><p>44.27</p><p>161.40</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>10-40-40</p><p>10.97</p><p>539.94</p><p>0.84</p><p>Elasticsearch-9.0-BBQ</p><p>10-50-50</p><p>11.00</p><p>535.73</p><p>0.85</p><p>Elasticsearch-9.0-BBQ</p><p>10-500-500</p><p>19.52</p><p>341.45</p><p>0.93</p><p>Elasticsearch-9.0-BBQ</p><p>10-750-750</p><p>22.94</p><p>295.19</p><p>0.94</p><p>OpenSearch-2.19-faiss</p><p>10-100-100</p><p>35.59</p><p>200.61</p><p>0.94</p><p>OpenSearch-2.19-faiss</p><p>10-1000-1000</p><p>156.81</p><p>58.30</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>10-1500-1500</p><p>181.79</p><p>42.97</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>10-200-200</p><p>47.91</p><p>155.16</p><p>0.95</p><p>OpenSearch-2.19-faiss</p><p>10-2000-2000</p><p>232.14</p><p>31.84</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>10-40-40</p><p>27.55</p><p>249.25</p><p>0.92</p><p>OpenSearch-2.19-faiss</p><p>10-50-50</p><p>28.78</p><p>245.14</p><p>0.92</p><p>OpenSearch-2.19-faiss</p><p>10-500-500</p><p>79.44</p><p>97.06</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>10-750-750</p><p>104.19</p><p>75.49</p><p>0.96</p><h3>리콜 @ 50 - 단순화</h3><p>이 수준의 리콜에서 Elasticsearch BBQ는 OpenSearch FAISS보다 <strong>최대 5배</strong> (평균 4.2배) 빠르며 평균 <strong>처리량이 3.9배(</strong> ) 더 많습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt486683f2c7a1d677/6a1709c2a6c2b995bde796a3/3189ffb330948b35854eeea9ae317d4846c14972-1600x681.png" alt="Recal @50 벡터 성능 비교 Elasticsearch BBQ와 Opensearch FAISS" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba830c6741784682/6a1709c4a292990627d00ff7/607383d674dcf0b8f94bfb1a450063f52fcbeb15-2060x876.png" alt="Elasticsearch BBQ는 OpenSearch FAISS보다 최대 5배(평균 4.2배) 빠르며 평균 3.9배 더 많은 처리량을 제공합니다." /><h4>상세 결과 - 리콜 @ 50%</h4><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt821775e7f87e5ede/6a1709c6a6c2b90af3e796a7/ebfffe0b776aad31dd03d315cfbf5aa098b41226-1600x789.png" alt="Recall@50 Elasticsearch BBQ 및 Opensearch FAISS 지연 시간 결과" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4f47784ed1017c15/6a1709c7e8fbce0fbe39fbf5/ae20cf870a65c400a2112bbad62eb56e244f549a-1600x799.png" alt="Recall@50 Elasticsearch BBQ 및 Opensearch FAISS 처리량 결과" /><p></p><p>작업</p><p>지연 시간 평균</p><p>처리량 평균</p><p>평균 회수율</p><p>Elasticsearch-9.0-BBQ</p><p>50-1000-1000</p><p>25.71</p><p>246.44</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>50-1200-1200</p><p>28.81</p><p>227.85</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>50-150-150</p><p>13.43</p><p>362.90</p><p>0.90</p><p>Elasticsearch-9.0-BBQ</p><p>50-1500-1500</p><p>33.38</p><p>202.37</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>50-200-200</p><p>12.99</p><p>406.30</p><p>0.91</p><p>Elasticsearch-9.0-BBQ</p><p>50-2000-2000</p><p>42.63</p><p>163.68</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>50-250-250</p><p>14.41</p><p>373.21</p><p>0.92</p><p>Elasticsearch-9.0-BBQ</p><p>50-500-500</p><p>17.15</p><p>341.04</p><p>0.93</p><p>Elasticsearch-9.0-BBQ</p><p>50-750-750</p><p>31.25</p><p>248.60</p><p>0.94</p><p>OpenSearch-2.19-faiss</p><p>50-1000-1000</p><p>125.35</p><p>62.53</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>50-1200-1200</p><p>143.87</p><p>54.75</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>50-150-150</p><p>43.64</p><p>130.01</p><p>0.89</p><p>OpenSearch-2.19-faiss</p><p>50-1500-1500</p><p>169.45</p><p>46.35</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>50-200-200</p><p>48.05</p><p>156.07</p><p>0.91</p><p>OpenSearch-2.19-faiss</p><p>50-2000-2000</p><p>216.73</p><p>36.38</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>50-250-250</p><p>53.52</p><p>142.44</p><p>0.93</p><p>OpenSearch-2.19-faiss</p><p>50-500-500</p><p>78.98</p><p>97.82</p><p>0.95</p><p>OpenSearch-2.19-faiss</p><p>50-750-750</p><p>103.20</p><p>75.86</p><p>0.96</p><h3>리콜 @ 100</h3><p>이 수준의 리콜에서 Elasticsearch BBQ는 OpenSearch FAISS보다 <strong>최대 5배 </strong>(평균 4.6배) 빠르며 평균 <strong>3.9배 더 많은 처리량을 </strong>제공합니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt380eb9165343a7b3/6a1709c9acf0882669be9ac5/d3f29db64cbde9956de1fa3ae64a75f15141a2bb-1600x681.png" alt="100개의 Elasticsearch BBQ와 Opensearch FAISS 결과 비교" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt505ce8aa70898390/6a1709cb1949f73a37e7a9bb/10aff7f8c61fdac895b9ba9c5342baf239ba3ffc-2072x864.png" alt="Elasticsearch BBQ와 Opensearch FAISS 지연 시간 및 처리량 성능 비교" /><h4>상세 결과 - 리콜 @ 100</h4><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb2a73e29940e9d6b/6a1709cccf4f257615b2d138/8790fdf9512b850447f6875fb69969f6f1d4da5f-1600x799.png" alt="세부 지연 시간 결과 - 100회 리콜 @ 100 Elasticsearch BBQ vs Opensearch FAISS" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte2c91ca21da03d96/6a1709ce0c4857d3fc01aa39/d47032fac6c288cd4eedd9f25001e417b2fa9d65-1600x787.png" alt="자세한 처리량 결과 - 100회 회상 @ 100 Elasticsearch BBQ 대 Opensearch FAISS." /><p></p><p>작업</p><p>latency.mean</p><p>throughput.mean</p><p>avg_recall</p><p>Elasticsearch-9.0-BBQ</p><p>100-1000-1000</p><p>27.82</p><p>243.22</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>100-1200-1200</p><p>31.14</p><p>224.04</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>100-1500-1500</p><p>35.98</p><p>193.99</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>100-200-200</p><p>14.18</p><p>403.86</p><p>0.88</p><p>Elasticsearch-9.0-BBQ</p><p>100-2000-2000</p><p>45.36</p><p>159.88</p><p>0.95</p><p>Elasticsearch-9.0-BBQ</p><p>100-250-250</p><p>14.77</p><p>433.06</p><p>0.90</p><p>Elasticsearch-9.0-BBQ</p><p>100-300-300</p><p>14.61</p><p>375.54</p><p>0.91</p><p>Elasticsearch-9.0-BBQ</p><p>100-500-500</p><p>18.88</p><p>340.37</p><p>0.93</p><p>Elasticsearch-9.0-BBQ</p><p>100-750-750</p><p>23.59</p><p>285.79</p><p>0.94</p><p>OpenSearch-2.19-faiss</p><p>100-1000-1000</p><p>142.90</p><p>58.48</p><p>0.95</p><p>OpenSearch-2.19-faiss</p><p>100-1200-1200</p><p>153.03</p><p>51.04</p><p>0.95</p><p>OpenSearch-2.19-faiss</p><p>100-1500-1500</p><p>181.79</p><p>43.20</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>100-200-200</p><p>50.94</p><p>131.62</p><p>0.83</p><p>OpenSearch-2.19-faiss</p><p>100-2000-2000</p><p>232.53</p><p>33.67</p><p>0.96</p><p>OpenSearch-2.19-faiss</p><p>100-250-250</p><p>57.08</p><p>131.23</p><p>0.87</p><p>OpenSearch-2.19-faiss</p><p>100-300-300</p><p>62.76</p><p>120.10</p><p>0.89</p><p>OpenSearch-2.19-faiss</p><p>100-500-500</p><p>84.36</p><p>91.54</p><p>0.93</p><p>OpenSearch-2.19-faiss</p><p>100-750-750</p><p>111.33</p><p>69.95</p><p>0.94</p><h2>BBQ 개선 사항</h2><p>BBQ는 첫 출시 이후 많은 발전을 거듭해 왔습니다. 비교를 위해 8.16 버전에서 현재 버전과 함께 실행한 벤치마크를 포함시켰는데, 그 이후 리콜과 지연 시간이 어떻게 개선되었는지 확인할 수 있습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9f1f7ae1bb425a3a/6a1709cf67045bde8e45c192/45a0acfe5985bff28ccada76ec4eca190fe65f72-1600x799.png" alt="Elasticsearch 8.16 BBQ를 벤치마킹한 Elasticsearch 9.0 BBQ 지연 시간 리콜 개선 사항" /><p>Elasticsearch 8.18과 9.0에서는 벡터를 정량화하기 위한 핵심 알고리즘을 다시 작성했습니다. 따라서 8.16의 BBQ도 좋았지만 최신 버전은 훨씬 더 좋습니다. 자세한 내용은 <a href="https://www.elastic.co/kr/search-labs/blog/optimized-scalar-quantization-elasticsearch">여기와</a> <a href="https://www.elastic.co/kr/search-labs/blog/scalar-quantization-optimization">여기에서</a> 확인할 수 있습니다. 즉, 모든 벡터는 최적화된 스칼라 사분위수를 통해 개별적으로 정량화됩니다. 그 결과, 사용자는 성능 저하 없이 벡터 검색의 정확도가 높아져 Elasticsearch의 벡터 검색이 더욱 강력해지는 이점을 누릴 수 있습니다.</p><h2>결론</h2><p>이 Elasticsearch BBQ와 OpenSearch FAISS 간의 성능 비교에서 Elasticsearch는 벡터 검색에서 OpenSearch보다 훨씬 뛰어난 성능을 발휘하여 다양한 수준의 리콜에서 평균적으로 최대 5배 빠른 쿼리 속도와 3.9배 높은 처리량을 달성했습니다.</p><p>주요 결과는 다음과 같습니다:</p><ul><li><p><strong>Recall@10</strong>: Elasticsearch BBQ는 OpenSearch FAISS에 비해 최대 5배(평균 3.9배) 빠르며 평균 3.2배 더 많은 처리량을 제공합니다.</p></li><li><p><strong>Recall@50</strong>: Elasticsearch BBQ는 OpenSearch FAISS에 비해 최대 5배(평균 4.2배) 빠르며 평균 3.9배 더 많은 처리량을 제공합니다.</p></li><li><p><strong>Recall@100</strong>: Elasticsearch BBQ는 OpenSearch FAISS에 비해 최대 5배(평균 4.6배) 빠르며 평균 3.9배 더 많은 처리량을 제공합니다.</p></li></ul><p>이러한 결과는 특히 고차원 벡터 검색 시나리오에서 Elasticsearch BBQ의 효율성과 성능 이점을 강조합니다. Elasticsearch 8.16에 도입된 더 나은 이진 양자화(BBQ) 기술은 높은 순위 품질을 유지하면서 상당한 메모리 절감(~95%)을 제공하므로 대규모 벡터 검색 애플리케이션에 탁월한 선택이 될 수 있습니다.</p><p>Elastic에서는 RAG(검색 증강 생성)를 비롯한 검색 및 검색 사용 사례를 위한 최고의 벡터 데이터베이스를 제공하기 위해 Apache Lucene과 Elasticsearch를 개선하기 위해 끊임없이 혁신하고 있습니다. <a href="https://www.elastic.co/kr/search-labs/blog/optimized-scalar-quantization-elasticsearch">최근의 발전으로</a> 성능이 크게 향상되어 이전보다 벡터 검색 속도가 빨라지고 공간 효율성이 높아졌으며, 이는 루씬 10에서 얻은 이점을 기반으로 합니다. 이 블로그는 이러한 혁신의 또 다른 예시입니다.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-bbq-vs-opensearch-faiss</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-bbq-vs-opensearch-faiss</guid>
    <category><![CDATA[벡터 데이터베이스]]></category>
    <dc:creator><![CDATA[Ugo Sangiorgi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd76ada1eebfe05cd/6a1709d1a29299ed29d00ffb/796de4829e29566f1f3efa2482f5c3e54b31b1d6-1536x1024.png" length="0" type="image/png"/>
    <pubDate>Tue, 15 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearch와 OpenSearch: 벡터 검색 성능 비교]]></title>
    <description><![CDATA[Elasticsearch는 벡터 검색에서 별도 설정 없이 OpenSearch보다 2~12배 더 빠릅니다.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/search-labs/blog/elasticsearch-opensearch-vector-search-performance-comparison#up-to-12x-faster-out-of-the-box">요약: Elasticsearch는 최대 12배 더 빠릅니다</a> - Elastic에서는 커뮤니티로부터 시맨틱 검색/벡터 검색 영역에서 특히 Elasticsearch와 OpenSearch의 성능 차이를 명확히 해달라는 요청을 많이 받았습니다. 따라서 명확한 데이터 기반의 비교를 제공하기 위해 이 성능 테스트를 수행했으며, 그 취지는 모호함 없이 사용자에게 명확한 사실만을 전달한다는 데 있었습니다. 결과는 <strong>Elasticsearch가 벡터 검색에서 OpenSearch보다 최대 12배 더 빨라</strong>, 더 적은 컴퓨팅 리소스를 필요로 한다는 것을 보여줍니다. 이는 검색 및 조회용으로 Lucene을 최고의 벡터 데이터베이스로 통합하려는 Elastic의 노력을 반영합니다.</p><p>벡터 검색은 특히 AI, 머신 러닝 같은 분야에서 유사성 검색을 수행하는 방식을 혁신하고 있습니다. 벡터 임베딩 모델의 채택이 증가함에 따라 수백만 개의 고차원 벡터를 효율적으로 검색하는 능력이 중요해지고 있습니다.</p><p>벡터 데이터베이스를 지원하는 데 있어 Elastic과 OpenSearch는 눈에 띄게 다른 접근 방식을 취해 왔습니다. Elastic은 Elasticsearch와 함께 Apache Lucene을 최적화하는 데 막대한 투자를 진행했으며, 이를 통해 벡터 검색 애플리케이션 분야에서 업계 최고 수준의 옵션으로 자리매김했습니다. 이에 비해 OpenSearch는 Lucene의 범위를 넘어 다른 벡터 검색 구현을 통합하며 그 중점 분야를 확장했습니다. Elastic은 전략적으로 Lucene에 집중하여, Elasticsearch 버전에서 고도로 통합된 지원을 제공해 각 구성 요소가 서로의 기능을 보완하고 강화하는 향상된 기능 세트를 제공할 수 있게 되었습니다.</p><p>이 블로그에서는 다양한 구성과 벡터 엔진에 대해 Elasticsearch 8.14와 OpenSearch 2.14를 자세히 비교하고 있습니다. 이 성능 분석에서 Elasticsearch는 벡터 검색 작업에서 우수한 플랫폼임이 입증되었으며, 앞으로 출시될 <a href="https://www.elastic.co/search-labs/blog/vector-similarity-computations-ludicrous-speed">기능들</a>은 이러한 차이를 더욱 <a href="https://www.elastic.co/search-labs/blog/elasticsearch-lucene-vector-database-gains">크게</a> 확대할 것입니다. OpenSearch와 비교했을 때 모든 벤치마크 트랙에서 뛰어난 성능을 보였으며, <strong>평균적으로 2~12배 더 빠른 성능을 제공했습니다</strong>. 이는 <code>so_vector</code> (2M 벡터, 768D), <code>openai_vector</code> (2.5M 벡터, 1536D), <code>dense_vector</code> (10M 벡터, 96D)를 포함한 다양한 벡터 수와 차원을 사용하는 시나리오에서 진행되었으며, 모든 항목은 Google 클라우드에서 필요한 인프라를 프로비저닝하기 위한 Terraform 스크립트와 테스트 실행용 Kubernetes 매니페스트와 함께 <a href="https://github.com/elastic/elasticsearch-opensearch-vector-performance">이 리포지토리</a>에서 확인할 수 있습니다.</p><p>이 블로그에 자세히 설명된 결과는 <a href="https://www.elastic.co/blog/elasticsearch-opensearch-performance-gap">이전에 발표되고 제3자가 검증한 연구</a> 결과를 보완합니다. 해당 연구에서는 Elasticsearch가 가장 일반적인 검색 분석 작업(텍스트 쿼리, 정렬, 범위, 날짜 히스토그램, 용어 필터링)에서 OpenSearch보다 40%–140% 더 빠르다는 것을 보여줍니다. 이제 또 다른 차별화 요소인 벡터 검색을 추가할 수 있습니다.</p><h2>기본 설정으로 최대 12배 더 빠른 성능</h2><p>4개의 벡터 데이터 세트에 대한 집중 벤치마크에는 근사 KNN 및 정확한 KNN 검색이 모두 포함되었습니다. 다양한 크기, 차원, 구성을 고려하여 총 <code>40.189.820</code> 개의 캐시되지 않은 검색 요청에 대해 수행했습니다. 결과: <strong>Elasticsearch가 벡터 검색에서 OpenSearch보다 최대 12배 더 빨라</strong>, 더 적은 컴퓨팅 리소스를 필요로 한다는 것을 보여줍니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt34b83c6eba3bcb6e/6a17d727dbb4ff18d6fb54fb/cdb26e91f085b90e9b12aeb8fee53b04d365ecae-1440x1156.webp" alt="p90 평균" /><p>그림 1: Elasticsearch와 OpenSearch의 다양한 조합에서 수행된 ANN 및 정확한 KNN 작업 그룹.</p><p><code>knn-10-100</code> 같은 그룹은  및  설정의 KNN 검색을 의미합니다. HNSW 벡터 검색에서 는 쿼리 벡터에 대해 검색할 최근접 이웃의 수를 결정합니다. 결과적으로 얼마나 많은 유사한 벡터를 찾을지 지정합니다. 은 각 세그먼트에서 검색할 후보 벡터의 수를 설정합니다. 후보자가 많을수록 정확도가 향상되지만 더 많은 계산 리소스가 필요합니다.</p><p>또한 다양한 양자화 기법과 엔진별 최적화를 활용하여 테스트했으며, 각 트랙, 작업, 벡터 엔진에 대한 자세한 결과는 아래에서 확인할 수 있습니다.</p><h2>정확한 KNN과 근사 KNN</h2><p>다양한 데이터 세트와 사용 사례를 다룰 때, 벡터 검색에 적합한 접근 방식은 달라집니다. 이 블로그에서 <code>knn-*</code> 로 표시된 모든 작업은 <code>knn-10-100</code> 처럼 <strong>근사 KNN</strong>을 사용하고, <code>script-score-*</code> 는 <strong>정확한 KNN</strong>을 참조합니다. 그렇다면 이 둘의 차이점은 무엇이며, 왜 중요할까요?</p><p>본질적으로 더 큰 데이터 세트를 처리할 때는, 확장성이 뛰어난 근사 K-최근접 이웃(ANN) 방법이 선호됩니다. 필터링 프로세스가 필요한 상대적으로 작은 데이터 세트의 경우, 정확한 KNN 방법이 이상적입니다.</p><p>정확한 KNN은 무차별 대입 방식을 사용하여 하나의 벡터와 데이터 세트의 다른 모든 벡터 사이의 거리를 계산합니다. 그런 다음 이 거리의 순위를 매겨 개의 최근접 이웃을 찾습니다. 이 방법은 정확한 일치를 보장하지만, 대규모의 고차원 데이터 세트에 대한 확장성 문제가 있습니다. 그러나 정확한 KNN이 필요한 경우가 많이 있습니다.</p><ul><li><p><strong>리스코어링</strong>: 어휘 또는 시맨틱 검색 후 벡터 기반 리스코어링을 포함하는 시나리오에서는 정확한 KNN이 필수적입니다. 예를 들어, 제품 검색 엔진에서 초기 검색 결과는 텍스트 쿼리(예: 키워드, 카테고리)를 기반으로 필터링할 수 있으며, 필터링된 항목과 연관된 벡터를 사용하여 보다 정확한 유사성 평가를 수행할 수 있습니다.</p></li><li><p><strong>개인화</strong>: 많은 사용자가 각각 비교적 적은 수(예: 1백만)의 고유 벡터로 표현될 때, 사용자별 메타데이터(예: user_id)로 색인을 정렬하고 벡터를 이용한 무차별 대입 스코어링이 효율적입니다. 이 접근 방식을 사용하면 개별 사용자 선호도에 맞춘 정확한 벡터 비교를 기반으로, 개인화된 추천이나 콘텐츠 제공이 가능합니다.</p></li></ul><p>따라서 정확한 KNN은 벡터 유사도에 기반한 최종 순위와 추천이 정확하며 사용자 선호도에 맞게 조정됩니다.</p><p>반면에 근사 KNN(ANN)은 대규모 고차원 데이터 세트에서 정확한 KNN보다 데이터를 더 빠르고 효율적으로 검색할 수 있는 방법을 사용합니다. 쿼리와 모든 지점 사이의 가장 가까운 정확한 거리를 측정하여 계산 및 확장 문제로 이어지는 무차별 대입 방식 대신, ANN은 특정 기술을 사용해 데이터 세트에서 검색 가능한 벡터의 인덱스와 차원을 효율적으로 재구성합니다. 이로 인해 약간의 부정확성이 발생할 수 있지만, 검색 프로세스의 속도가 크게 향상되어 대규모 데이터 세트를 처리하는 데 효과적인 대안이 됩니다.</p><p>이 블로그에서는 <code>knn-*</code> 로 표시된 모든 작업은 <code>knn-10-100</code> 과 같이 <strong>근사 KNN</strong>을 사용하고, <code>script-score-*</code> 는 <strong>정확한 KNN</strong>을 참조합니다.</p><h2>테스트 방법론</h2><p>Elasticsearch와 OpenSearch는 BM25 검색 작업을 위한 API 측면에서 비슷하지만, 후자가 전자의 포크이기 때문에 포크 이후에 도입된 벡터 검색에는 해당되지 않습니다. OpenSearch는 알고리즘에 있어서 Elasticsearch와는 다른 접근 방식을 취했습니다. <code>lucene</code> 외에도, 각각 고유한 구성과 제한 사항을 가진 2개의 다른 엔진인 <code>nmslib</code> 및 <code>faiss</code> 를 도입했습니다. 예를 들어, OpenSearch의 <code>nmslib</code> 은 많은 사용 사례에서 필수적인 기능인 필터를 허용하지 않습니다.</p><p>3개 엔진 모두 계층적으로 탐색 가능한 작은 세계(Hierarchical Navigable Small World, HNSW) 알고리즘을 사용합니다. HNSW 알고리즘은 근사 최근접 이웃을 검색하는 데 효율적이며 고차원 데이터를 처리할 때 특히 강력합니다. <code>faiss</code>는 두 번째 알고리즘인 <code>ivf</code>도 지원하지만, 데이터 세트에 대한 사전 학습이 필요하기 때문에, 여기서는 HNSW에만 집중하려고 합니다. HNSW의 핵심 아이디어는 데이터를 여러 계층의 연결된 그래프로 구성하는 것이며, 각 계층은 데이터 세트의 다양한 세분성을 나타냅니다. 검색은 가장 거친 보기를 제공하는 최상위 레이어에서 시작하여 기본 수준에 도달할 때까지 점점 더 세밀한 레이어로 진행됩니다.</p><p>두 검색 엔진은 모두 공정한 테스트 근거를 확보하기 위해 통제된 환경에서 동일한 조건으로 테스트되었습니다. 적용된 방법은 Elasticsearch, OpenSearch, Rally에 대한 전용 Node 풀을 사용하여 <a href="https://www.elastic.co/blog/elasticsearch-opensearch-performance-gap#testing-methodology">이전에 게시된 성능 비교</a>와 유사합니다. <a href="https://github.com/elastic/elasticsearch-opensearch-vector-performance/blob/main/terraform/main.tf">terraform 스크립트</a>는 (모든 소스와 함께) Kubernetes 클러스터를 프로비저닝하는 데 사용할 수 있습니다.</p><ul><li><p>3개의 <code>e2-standard-32</code> 머신(128GB RAM 및 32개의 CPU)이 있는 Elasticsearch용 Node 풀 1개</p></li><li><p>3개의 <code>e2-standard-32</code> 머신(128GB RAM 및 32개의 CPU)이 있는 OpenSearch용 Node 풀 1개</p></li><li><p>2개의 <code>t2a-standard-16</code> 머신(64GB RAM 및 16개의 CPU)이 있는 Rally용 Node 풀 1개</p></li></ul><p>각 '트랙'(또는 테스트)은 서로 다른 엔진, 서로 다른 구성, 서로 다른 벡터 유형을 포함하는 각 구성에 대해 10회씩 실행되었습니다. 트랙에는 트랙에 따라 1,000번에서 10,000번 반복되는 작업이 있습니다. 예를 들어 네트워크 시간 초과로 인해 트랙의 작업 중 하나가 실패하면, 모든 작업이 폐기되므로 모든 결과는 문제 없이 시작되고 완료된 트랙을 나타냅니다. 모든 테스트 결과는 통계적으로 검증되어, 개선이 우연이 아님을 보장합니다.</p><h2>자세한 결과</h2><p>왜 평균 지연 시간이 아닌 99번째 백분위수를 사용하여 비교해야 할까요? 한 예로 특정 지역의 평균 주택 가격을 들어 보겠습니다. 평균 가격은 비싼 지역을 나타낼 수 있지만, 자세히 살펴보면 대부분의 주택은 훨씬 낮은 가격에 거래되고 일부 고급 부동산만 평균 수치를 부풀리고 있는 것으로 드러날 수 있습니다. 이는 평균 가격이 해당 지역의 주택 가치 전체를 정확하게 나타내지 못할 수 있음을 보여줍니다. 이는 응답 시간를 조사하는 것과 유사하며, 평균값은 중요한 문제를 숨길 수 있습니다.</p><h4>작업</h4><ul><li><p>근사 KNN(k:10 n:50)</p></li><li><p>근사 KNN(k:10 n:100)</p></li><li><p>근사 KNN(k:100 n:1000)</p></li><li><p>근사 KNN(k:10 n:50) 및 키워드 필터 적용</p></li><li><p>근사 KNN(k:10 n:100) 및 키워드 필터 적용</p></li><li><p>근사 KNN(k:100 n:1000) 및 키워드 필터 적용</p></li><li><p>근사 KNN(k:10 n:100) 및 인덱싱 병행</p></li><li><p>정확한 KNN(스크립트 점수)</p></li></ul><h4>벡터 엔진</h4><ul><li><p><code>lucene</code> Elasticsearch와 OpenSearch 모두, 버전 9.10에서</p></li><li><p><code>faiss</code> OpenSearch에서</p></li><li><p><code>nmslib</code> OpenSearch에서</p></li></ul><h4>벡터 유형</h4><ul><li><p><code>hnsw</code> Elasticsearch 및 OpenSearch에서</p></li><li><p><code>int8_hnsw</code> Elasticsearch에서(자동 8비트 양자화 적용 HNSW: <a href="https://www.elastic.co/search-labs/blog/evaluating-scalar-quantization">링크</a>)</p></li><li><p><code>sq_fp16 hnsw </code>OpenSearch에서(자동 16비트 양자화 적용 HNSW: <a href="https://opensearch.org/docs/2.14/search-plugins/knn/knn-vector-quantization#faiss-16-bit-scalar-quantization">링크</a>)</p></li></ul><h4>기본 설정 상태에서 바로 사용 가능, 동시 세그먼트 검색 지원</h4><p>아시다시피, Lucene은 Java로 작성된 고성능 텍스트 검색 엔진 라이브러리로 Elasticsearch, OpenSearch, Solr 등 많은 검색 플랫폼의 중추적인 역할을 합니다. 핵심적으로 Lucene은 데이터를 세그먼트로 구성하며, 세그먼트는 본질적으로 독립된 인덱스로서 Lucene이 검색을 보다 효율적으로 실행할 수 있게 해 줍니다. 따라서 Lucene 기반 검색 엔진에 검색을 요청하면, 해당 세그먼트에서 순차적으로 또는 병렬로 검색이 실행됩니다.</p><p>OpenSearch는 동시 세그먼트 검색을 선택적 플래그로 도입했지만 기본적으로 사용하지 않습니다. <a href="https://opensearch.org/docs/latest/search-plugins/concurrent-segment-search/">여기</a>에 자세히 설명된 대로 특수 인덱스 설정 <code>index.search.concurrent_segment_search.enabled</code>을 사용하여 활성화해야 하며, 몇 가지 <a href="https://opensearch.org/docs/latest/search-plugins/concurrent-segment-search/#other-considerations">제한 사항</a>이 있습니다.</p><p>반면 Elasticsearch는 <a href="https://github.com/elastic/elasticsearch/pull/101230">기본 설정으로</a> 세그먼트를 동시에 검색합니다. 따라서 이 블로그에서 비교할 때 다양한 벡터 엔진과 벡터 유형뿐만 아니라 다양한 구성도 고려됩니다.</p><ul><li><p>Elasticsearch ootb: 기본 설정 상태에서 바로 사용 가능한 Elasticsearch, 동시 세그먼트 검색 지원;</p></li><li><p>OpenSearch ootb: 동시 세그먼트 검색이 기본적으로 활성화되지 않은 상태;</p></li><li><p>OpenSearch css: 동시 세그먼트 검색이 활성화된 상태</p></li></ul><p>이제 테스트한 각 벡터 데이터 세트에 대한 자세한 결과를 살펴보겠습니다.</p><h2>250만 개의 벡터, 1,536차원(openai_vector)</h2><p>가장 간단하지만 차원 면에서 가장 큰 트랙인 <a href="https://github.com/elastic/rally-tracks/edit/master/openai_vector">openai_vector</a>부터 시작합니다. 이 트랙은 OpenAI의 <a href="https://openai.com/blog/new-and-improved-embedding-model">text-embedding-ada-002 모델</a>을 사용하여 생성된 임베딩으로 강화된 <a href="https://huggingface.co/datasets/BeIR/nq">NQ 데이터 세트</a>를 사용합니다. 근사 KNN만 테스트하고 작업은 5개뿐이므로 가장 간단합니다. 인덱싱 없이 독립형으로, 인덱싱과 함께, 단일 클라이언트와 8개의 동시 클라이언트를 사용하여 테스트합니다.</p><h3>작업</h3><ul><li><p><strong>standalone-search-knn-10-100-multiple-clients</strong>: 8개의 클라이언트로 250만 개의 벡터 동시에 검색(k: 10, n:100)</p></li><li><p><strong>standalone-search-knn-100-1000-multiple-clients</strong>: 8개의 클라이언트로 250만 개의 벡터 동시에 검색(k: 100, n:1000)</p></li><li><p><strong>standalone-search-knn-10-100-single-client</strong>: 단일 클라이언트로 250만 개의 벡터 검색(k: 10, n: 100)</p></li><li><p><strong>standalone-search-knn-100-1000-single-client</strong>: 단일 클라이언트로 250만 개의 벡터 검색(k: 100, n: 1000)</p></li><li><p><strong>parallel-documents-indexing-search-knn-10-100</strong>: 250만 개의 벡터 검색하는 동시에 추가로 100,000개의 문서를 색인(k:10, n:100).</p></li></ul><p>평균 p99 성능은 다음과 같이 요약됩니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf5791848eb0c12fb/6a17d72925daab9cae08a09e/eea0b2b49c690baada3e09d6968e513bfffe51a9-1440x318.webp" alt="openai_vector 표" /><p>여기서 k:10 및 n:100 조건에서 인덱싱(예: 읽기+쓰기)과 함께 벡터 검색을 수행할 때 Elasticsearch가 OpenSearch보다 <strong>3~ 8배 정도 빠르다</strong>는 것을 관찰했습니다. 또한 동일한  및  조건에서, 인덱싱 없이 수행할 경우 <strong>2~3배 더 빠르다</strong>는 결과가 나왔습니다. :100 및 :1000(<em>standalone-search-knn-100-1000-single-client</em> 및 <em>standalone-search-knn-100-1000-multiple-clients</em>)에서 Elasticsearch는 평균적으로 OpenSearch보다 <strong>2~7배</strong> 더 빠릅니다.</p><p>자세한 결과에서는 정확한 사례와 벡터 엔진을 비교해 보여줍니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdbe41d3187ced7ec/6a17d72a445de951c44cff4c/a7a761ed631d3e6211beb83d9d93d752d10123c9-1440x1728.webp" alt="openai_vector" /><h4>리콜</h4><p></p><p>knn-recall-10-100</p><p>knn-recall-100-1000</p><p>Elasticsearch-8.14.0@lucene-hnsw</p><p>0.969485</p><p>0.995138</p><p>Elasticsearch-8.14.0@lucene-int8_hnsw</p><p>0.781445</p><p>0.784817</p><p>OpenSearch-2.14.0@lucene-hnsw</p><p>0.96519</p><p>0.995422</p><p>OpenSearch-2.14.0@faiss</p><p>0.984154</p><p>0.98049</p><p>OpenSearch-2.14.0@faiss-sq_fp16</p><p>0.980012</p><p>0.97721</p><p>OpenSearch-2.14.0@nmslib</p><p>0.982532</p><p>0.99832</p><h2>1,000만 개의 벡터, 96차원(dense_vector)</h2><p>1천만 개의 벡터, 96차원으로 구성된 <a href="https://github.com/elastic/rally-tracks/tree/master/dense_vector">dense_vector</a>에서. <a href="https://big-ann-benchmarks.com/">Yandex DEEP1B</a> 이미지 데이터 세트를 기반으로 합니다. 데이터 세트는 <code>learn.350M.fbin</code>이라는 '샘플 데이터' 파일의 처음 1천만 개의 벡터로 생성됩니다. 검색 작업은 '쿼리 데이터' 파일 쿼리 <code>public.10K.fbin</code>의 벡터를 사용합니다.</p><p>Elasticsearch와 OpenSearch는 이 데이터 세트에서 매우 우수한 성능을 발휘합니다. 특히 일반적으로 읽기 전용 인덱스에서 수행되는 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html">강제 병합</a> 이후에는 더욱 그렇습니다. 이는 인덱스를 조각 모음하여 검색 대상으로 단일 '테이블'을 구성하는 것과 유사합니다.</p><h3>작업</h3><p>각 작업은 100개의 요청으로 워밍업한 후 1,000개의 요청을 측정합니다.</p><ul><li><p><strong>knn-search-10-100</strong>: 1천만 개의 벡터 검색(k: 10, n: 100)</p></li><li><p><strong>knn-search-100-1000</strong>: 1천만 개의 벡터 검색(k: 100, n: 1000)</p></li><li><p><strong>knn-search-10-100-force-merge</strong>: 강제 병합 후 1천만 개의 벡터 검색(k: 10, n: 100)</p></li><li><p><strong>knn-search-100-1000-force-merge</strong>: 강제 병합 후 1천만 개의 벡터 검색(k: 100, n:1000)</p></li><li><p><strong>knn-search-100-1000-concurrent-with-indexing</strong>: 1천만 개의 벡터를 검색하면서 동시에 <a href="https://github.com/elastic/rally-tracks/blob/master/dense_vector/challenges/default.json#L76C36-L76C37">데이터 세트의 5%</a> 업데이트(k: 100, n: 1000)</p></li><li><p><strong>script-score-query</strong>: <a href="https://github.com/elastic/rally-tracks/blob/master/dense_vector/queries.json">2천 개의 특정 벡터</a>에 대한 정확한 KNN 검색.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4629d06af85eb96c/6a17d72c6864a423e7b685dc/174995e0a2156d86359cdb7aa446dfaae6312ea4-1440x316.webp" alt="dense_vector" /><p>Elasticsearch와 OpenSearch 모두 근접 KNN에서 우수한 성능을 보였습니다. <em>knn-search-100-1000-force-merge</em>와 <em>knn-search-10-100-force-merge</em>에서 인덱스가 병합되면(즉, 세그먼트가 하나만 있는 경우) <code>nmslib</code> 와 <code>faiss</code>를 사용할 때 모두 약 15ms로 매우 근접하지만 OpenSearch가 다른 엔진보다 성능이 더 좋습니다.</p><p>그러나 <em>knn-search-10-100</em>과 <em>knn-search-100-1000</em>에서 인덱스에 여러 세그먼트가 있는 경우(인덱스가 문서에 대한 업데이트를 받는 일반적인 상황) Elasticsearch는 대기 시간을 약 7ms와 16ms로 유지하는 반면, 다른 모든 OpenSearch 엔진은 더 느립니다.</p><p>또한 인덱스를 동시에 검색하고 작성하는 경우<em>(knn-search-100-1000-concurrent-with-indexing</em>) Elasticsearch는 지연 시간을 15ms(13.8ms) 미만으로 유지하여 OpenSearch(49.3ms)보다 거의 <strong>4배 빠르고</strong>, 동시 세그먼트 검색이 활성화된 경우에도 여전히 더 빠릅니다(17.9ms). 하지만 차이가 너무 작아 의미 있는 수준이라고 보기는 어렵습니다.</p><p>정확한 KNN의 경우 차이가 훨씬 큽니다. Elasticsearch는 OpenSearch보다 <strong>6배 더 빠릅니다</strong>(약 260ms vs. 1600ms).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt254f43bcaa3dbfc2/6a17d72ddbb4ffc780fb54ff/17aec6be31117440bc4d1f99984aed95df1c4f6b-1440x1728.webp" alt="dense_vector" /><h4>리콜</h4><p></p><p>knn-recall-10-100</p><p>knn-recall-100-1000</p><p>Elasticsearch-8.14.0@lucene-hnsw</p><p>0.969843</p><p>0.996577</p><p>Elasticsearch-8.14.0@lucene-int8_hnsw</p><p>0.775458</p><p>0.840254</p><p>OpenSearch-2.14.0@lucene-hnsw</p><p>0.971333</p><p>0.996747</p><p>OpenSearch-2.14.0@faiss</p><p>0.9704</p><p>0.914755</p><p>OpenSearch-2.14.0@faiss-sq_fp16</p><p>0.968025</p><p>0.913862</p><p>OpenSearch-2.14.0@nmslib</p><p>0.9674</p><p>0.910303</p><h2>2백만 개의 벡터, 768차원(so_vector)</h2><p>이 <a href="https://github.com/elastic/rally-tracks/tree/master/so_vector">트랙</a> <code>so_vector</code>은 2022년 4월 21일에 <a href="https://archive.org/download/stackexchange/stackoverflow.com-Posts.7z">다운로드한 StackOverflow 게시물 덤프</a>에서 파생되었습니다. 질문 문서만 포함되어 있으며, 답변 문서는 모두 제거되었습니다. 각 질문 제목은 문장 변환기 모델 <a href="https://huggingface.co/sentence-transformers/multi-qa-mpnet-base-cos-v1">multi-qa-mpnet-base-cos-v1</a>을 사용하여 벡터로 인코딩되었습니다. 이 데이터 세트에는 처음 2백만 개의 질문이 포함되어 있습니다.</p><p>이전 트랙과 달리, 각 문서에는 필터링 및 하이브리드 검색을 통한 근접 KNN과 같은 테스트 기능을 지원하기 위해 벡터 외에 다른 필드가 포함되어 있습니다. OpenSearch용<code>nmslib</code> 는 <a href="https://opensearch.org/docs/latest/search-plugins/knn/filter-search-knn/#k-nn-search-with-filters">필터를 지원하지 않기 때문에</a> 이 테스트에는 포함되지 않았습니다.</p><h3>작업</h3><p>각 작업은 100개의 요청으로 워밍업한 후, 100개의 요청을 측정합니다. 테스트에는 16개의 검색 유형 * 2개의 서로 다른 k 값 * 3개의 서로 다른 n 값이 포함되어 있으므로, 단순화를 위해 작업을 그룹화했습니다.</p><ul><li><p><strong>knn-10-50</strong>: 필터 없이 2백만 개의 벡터 검색(k:10, n:50)</p></li><li><p><strong>knn-10-50-filtered</strong>: <a href="https://github.com/elastic/rally-tracks/blob/master/so_vector/operations/default.json">필터를 적용</a>하여 2백만 개의 벡터 검색(k:10, n:50)</p></li><li><p><strong>knn-10-50-after-force-merge</strong>: 강제 병합 후 필터를 적용하여 2백만 개의 벡터 검색(k:10, n:50)</p></li><li><p><strong>knn-10-100</strong>: 필터 없이 2백만 개의 벡터 검색(k:10, n:100)</p></li><li><p><strong>knn-10-100-filtered</strong>: <a href="https://github.com/elastic/rally-tracks/blob/master/so_vector/operations/default.json">필터를 적용하여</a> 2백만 개의 벡터 검색(k:10, n:100)</p></li><li><p><strong>knn-10-100-after-force-merge</strong>: 강제 병합 후 필터를 적용하여 2백만 개의 벡터 검색(k:10, n:100)</p></li><li><p><strong>knn-100-1000</strong>: 필터 없이 2백만 개의 벡터 검색(k:100, n:1000)</p></li><li><p><strong>knn-100-1000-filtered</strong>: <a href="https://github.com/elastic/rally-tracks/blob/master/so_vector/operations/default.json">필터를 적용하여</a> 2백만 개의 벡터 검색(k:100 , n:1000)</p></li><li><p><strong>knn-100-1000-after-force-merge</strong>: 강제 병합 후 필터를 적용하여 2백만 개의 벡터 검색(k:100, n:1000)</p></li><li><p><strong>exact-knn</strong>: <a href="https://github.com/elastic/rally-tracks/blob/master/so_vector/operations/default.json#L56">필터 적용 여부에 관계없이</a> 정확한 KNN 검색.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8b44e1306af35877/6a17d72f577262aca11bca3e/d4ed2982d55370cad4b2048b23ce97caa55017c0-1440x316.webp" alt="so_vector 표" /><p>Elasticsearch는 이 테스트에서 기본 설정 상태에서 OpenSearch보다 <strong>일관되게 빠릅니다</strong>. OpenSearch가 더 빠른 경우는 두 가지뿐이며, 그 차이도 크지 않습니다(<em>knn-10-100</em> 및 <em>knn-100-1000</em>). 필터와 함께 <em>knn-10-50</em>, <em>knn-10-100</em>, <em>knn-100-1000</em> 작업은 최대 <strong>7배</strong>(112ms vs 803ms)의 차이를 보입니다.</p><p>두 솔루션의 성능은 '강제 병합' 후에 균등해 지는 것으로 보이며, 이는 <em>knn-10-50-after-force-merge</em>, <em>knn-10-100-after-force-merge</em>, <em>knn-100-1000-after-force-merge</em> 에서 확인할 수 있습니다. 그러한 작업에서 <code>faiss</code>가 더 빠릅니다.</p><p>정확한 KNN의 성능은 다시 한 번 매우 다르게 나타났으며, 이번에는 Elasticsearch가 OpenSearch보다 <strong>13배 더 빨랐습니다</strong>(약 385ms vs 5262ms).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf80ccc7c2df84559/6a17d7314b055de00d43203f/615cb9228eb05ddd2e9512b3a6a5bc88d4088a1a-1440x1440.webp" alt="so_vector" /><h4>리콜</h4><p></p><p>knn-recall-10-100</p><p>knn-recall-100-1000</p><p>knn-recall-10-50</p><p>Elasticsearch-8.14.0@lucene-hnsw</p><p>1</p><p>1</p><p>1</p><p>Elasticsearch-8.14.0@lucene-int8_hnsw</p><p>1</p><p>0.986667</p><p>1</p><p>OpenSearch-2.14.0@lucene-hnsw</p><p>1</p><p>1</p><p>1</p><p>OpenSearch-2.14.0@faiss</p><p>1</p><p>1</p><p>1</p><p>OpenSearch-2.14.0@faiss-sq_fp16</p><p>1</p><p>1</p><p>1</p><p>OpenSearch-2.14.0@nmslib</p><p>0.9674</p><p>0.910303</p><p>0.976394</p><h2>Elasticsearch와 Lucene이 명백한 승자</h2><p>Elastic에서는 RAG(Retrieval-Augmented Generation)를 비롯한 검색 및 조회 사용 사례를 위한 최고의 벡터 데이터베이스를 제공할 수 있도록 Apache Lucene과 Elasticsearch를 끊임없이 혁신하고 있습니다. 최근의 발전으로 성능이 획기적으로 향상되어 벡터 검색이 이전보다 <a href="https://search-labs.elastic.co/search-labs/blog/elasticsearch-lucene-vector-database-gains">더 빠르고 공간 효율적</a>이 되었으며, 이는 Lucene 9.10에서 얻은 이점을 기반으로 합니다. 이 블로그는 최신 버전을 비교한 결과 Elasticsearch가 OpenSearch보다 최대 12배 빠르다는 연구를 소개합니다.</p><p>두 제품 모두 동일한 버전의 Lucene(<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/release-notes-8.14.0.html">Elasticsearch 8.14 릴리즈 노트</a> 및 <a href="https://github.com/opensearch-project/OpenSearch/blob/2.14/release-notes/opensearch.release-notes-2.14.0.md">OpenSearch 2.14 릴리즈 노트</a>)을 사용한다는 점은 주목할 만합니다.</p><p>Elastic의 빠른 혁신은 온프레미스 및 Elastic Cloud 고객뿐만 아니라 당사의 <a href="https://www.elastic.co/search-labs/blog/stateless-your-new-state-of-find-with-elasticsearch">무상태(stateless) 플랫폼</a>을 사용하는 고객에게도 더 많은 혜택을 가져다 줄 것입니다. <a href="https://www.elastic.co/search-labs/blog/int4-scalar-quantization-in-lucene">int4에 대한 스칼라 양자화</a> 지원과 같은 기능은 <a href="https://www.elastic.co/search-labs/blog/evaluating-scalar-quantization">int8 테스트</a>와 마찬가지로, 엄격한 테스트를 통해 고객이 재현율 저하 없이 이러한 기술을 활용할 수 있도록 보장할 것입니다.</p><p>AI 및 머신 러닝 애플리케이션의 확산으로 인해 최신 검색 엔진에서 벡터 검색 효율성은 타협할 수 없는 기능이 되고 있습니다. 대용량·고복잡 벡터 데이터의 요구를 충족할 수 있는 강력한 검색 엔진을 찾고 있는 조직에게는 Elasticsearch가 확실한 해답입니다.</p><p>기존 플랫폼을 확장하든 새로운 프로젝트를 시작하든, 벡터 검색 요구 사항을 위해 Elasticsearch를 통합하는 것은 가시적이고 장기적인 이점을 얻을 수 있는 전략적 움직임입니다. 입증된 성능 우위를 바탕으로 Elasticsearch는 차세대 검색 혁신을 이끌 준비가 되어 있습니다.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-opensearch-vector-search-performance-comparison</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-opensearch-vector-search-performance-comparison</guid>
    <category><![CDATA[벡터 데이터베이스]]></category>
    <category><![CDATA[Lucene]]></category>
    <dc:creator><![CDATA[Ugo Sangiorgi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5d70b25967c2194e/6a17d732b1e11383f879f0ca/13c3c0053e2968fb835ba2f90f34bec3a011b5c0-880x592.webp" length="0" type="image/webp"/>
    <pubDate>Wed, 26 Jun 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>