Blog

Elasticsearch BBQ vs. OpenSearch FAISS: comparación del rendimiento de la búsqueda vectorial

Una comparación de rendimiento entre Elasticsearch BBQ y OpenSearch FAISS.

Búsqueda vectorial con cuantificación binaria: Elasticsearch con BBQ es 5 veces más rápido que OpenSearch con FAISS. Elastic recibió solicitudes de nuestra comunidad para aclarar las diferencias de rendimiento entre Elasticsearch y OpenSearch, particularmente en el ámbito de la búsqueda semántica/búsqueda vectorial, por lo que realizamos estas pruebas de rendimiento para proporcionar comparaciones claras y basadas en datos.

Elasticsearch BBQ vs. OpenSearch FAISS - Comparación de retiradas de velocidad y rendimiento

Enfrentamiento de cuantificación binaria

Almacenar vectores de alta dimensión en su forma original puede requerir mucha memoria. Las técnicas de cuantificación comprimen estos vectores en una representación compacta, lo que reduce significativamente la huella de memoria. Luego, la búsqueda opera en el espacio comprimido, lo que reduce la complejidad computacional y hace que las búsquedas sean más rápidas, especialmente en grandes conjuntos de datos.

Elastic está comprometida a convertir Lucene en un motor vectorial de alto rendimiento. Introdujimos Better Binary Quantization (BBQ) en Elasticsearch 8.16 sobre Lucene y lo evolucionamos aún más en 8.18 y 9.0. BBQ se basa en un nuevo enfoque de cuantización escalar que reduce las dimensiones float32 a bits, ofreciendo una reducción de memoria del ~95% manteniendo una alta calidad de clasificación.

OpenSearch, por otro lado, emplea múltiples motores vectoriales: nmslib (ahora obsoleto), Lucene y FAISS. En un blog anterior, comparamos Elasticsearch y OpenSearch para la búsqueda vectorial. Empleamos tres conjuntos de datos diferentes y probamos diferentes combinaciones de motores y configuraciones en ambos productos.

Este blog se centra en los algoritmos de cuantificación binaria disponibles actualmente en ambos productos. Probamos Elasticsearch con BBQ y OpenSearch con la cuantificación binaria de FAISS empleando la pista openai_vector Rally.

El objetivo principal fue evaluar el desempeño de ambas soluciones bajo el mismo nivel de recuperación. ¿Qué significa recordar ? La recuperación es una métrica que mide cuántos de los resultados relevantes son recuperados con éxito por un sistema de búsqueda.

En esta evaluación, recall@k es particularmente importante, donde k representa el número de resultados principales considerados. Recall@10, Recall@50 y Recall@100 medir cuántos de los resultados relevantes reales aparecen en los 10, 50 y 100 elementos principales recuperados, respectivamente. La recuperación se expresa en una escala de 0 a 1 (o de 0% a 100% de precisión). Y eso es importante porque estamos hablando de KNN aproximado (ANN) y no de KNN exacto, donde la recordación es siempre 1 (100%).

Para cada valor de k también especificamos n, que es el número de candidatos considerados antes de aplicar la clasificación final. Esto significa que para Recall@10, Recall@50 y Recall@100, el sistema primero recupera n candidatos empleando el algoritmo de cuantificación binaria y luego los clasifica para determinar si los k resultados principales contienen los elementos relevantes esperados.

Al controlar n, podemos analizar el equilibrio entre eficiencia y precisión. Un n más alto generalmente aumenta la recuperación, ya que hay más candidatos disponibles para la clasificación, pero también aumenta la latencia y disminuye el rendimiento. Por el contrario, un n más bajo acelera la recuperación, pero puede reducir la recordación si se incluyen muy pocos candidatos relevantes en el conjunto inicial.

En esta comparación, Elasticsearch demostró una latencia más baja y un rendimiento más alto que OpenSearch en configuraciones idénticas.

Metodología

La configuración completa, junto con los scripts de Terraform, los manifiestos de Kubernetes y la pista de Rally específica está disponible en este repositorio en openai_vector_bq.

Al igual que con los puntos de referencia anteriores, empleamos un clúster de Kubernetes compuesto por:

  • 1 pool de nodos para Elasticsearch 9.0 con 3 máquinas e2-standard-32 (128 GB de RAM y 32 CPU)

  • 1 grupo de nodos para OpenSearch 2.19 con 3 máquinas e2-standard-32 (128 GB de RAM y 32 CPU)

  • 1 grupo de nodos para Rally con 2 máquinas e2-standard-4 (16 GB de RAM y 4 CPU)

Montaje de la metodología Elasticsearch BBQ vs Opensearch FAISS

Configuramos un clúster de Elasticsearch versión 9.0 y un clúster de OpenSearch versión 2.19.

Tanto Elasticsearch como OpenSearch se probaron exactamente con la misma configuración: usamos openai_vector pista de Rally con algunas modificaciones , que emplea 2,5 millones de documentos del conjunto de datos NQ enriquecidos con incrustaciones generadas con el modelo text-embedding-ada-002 de OpenAI.

{
  "source-file": "open_ai_corpus-initial-indexing.json.bz2",
  "document-count": 2580961,
  "compressed-bytes": 32076749416,
  "uncompressed-bytes": 90263571686
}

Los resultados informan sobre la latencia y el rendimiento medidos en diferentes niveles de recuperación (recall@10, recall@50 y recall@100) empleando 8 clientes simultáneos para realizar operaciones de búsqueda. Usamos un solo fragmento y no réplicas.

Ejecutamos las siguientes combinaciones de k-n-rescore, p. ej. 10-2000-2000, o K:10, N:2000 y Rescore:2000 recuperarían los mejores K (10) sobre N candidatos (2000) aplicando un Rescore sobre 2000 resultados (que es equivalente a un "factor de sobremuestreo" de 1). Cada búsqueda se ejecutó 10.000 veces con 1000 búsquedas como calentamiento:

Recall@10

  • 10-40-40

  • 10-50-50

  • 10-100-100

  • 10-200-200

  • 10-500-500

  • 10-750-750

  • 10-1000-1000

  • 10-1500-1500

  • 10-2000-2000

Recall@50

  • 50-150-150

  • 50-200-200

  • 50-250-250

  • 50-500-500

  • 50-750-750

  • 50-1000-1000

  • 50-1200-1200

  • 50-1500-1500

  • 50-2000-2000

Recall@100

  • 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

Para replicar el punto de referencia, los manifiestos de Kubernetes para rally-elasticsearch y rally-opensearch tienen todas las variables relevantes externalizadas en un ConfigMap, disponible aquí (ES) y aquí (SO). El parámetro search_ops se puede personalizar para probar cualquier combinación de k, n y rescore.

Configuración de OpenSearch Rally

/k8s/rally-openai_vector-os-bq.yml

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]
      ]
    }

Configuración del índice de Opensearch

Las variables de ConfigMap se emplean en la configuración del índice, algunos parámetros se dejan sin cambios. La cuantización de 1 bit en OpenSearch se configura estableciendo el nivel de compresión en "32x".

index-vectors-only-mapping-with-docid-mapping.json

{
  "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
          }
        }
      }
    }
  }
}

Configuración de Elasticsearch Rally

/k8s/rally-openai_vector-es-bq.yml

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]
      ]
    }

Configuración del índice de Elasticsearch

index-vectors-only-mapping-with-docid-mapping.json

{
  "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
        }
      }
    }
  }
}

Resultados

Hay varias formas de interpretar los resultados. Tanto para la latencia como para el rendimiento, trazamos un gráfico simplificado y detallado en cada nivel de recuperación. Es fácil ver diferencias si consideramos que "más alto es mejor" para cada métrica. Sin embargo, la latencia es negativa (más baja es mejor), mientras que el rendimiento es positivo. Para los gráficos simplificados, usamos (recuperación / latencia) * 10000 (llamado simplemente "velocidad") y recuperación * rendimiento, por lo que ambas métricas significan que más velocidad y más rendimiento son mejores. Vamos a ello.

Recuperación @ 10 - simplificado

En ese nivel de recuperación, Elasticsearch BBQ es hasta 5 veces más rápido (3,9 veces más rápido en promedio) y tiene 3,2 veces más rendimiento en promedio que OpenSearch FAISS.

Elasticsearch BBQ es hasta 5 veces más rápido (3,9 veces más rápido de media) y tiene un rendimiento media 3,2 veces mayor que OpenSearch FAISS en velocidad y Recall@10
Elasticsearch BBQ es hasta 5 veces más rápido (3,9 veces más rápido de media) y tiene un rendimiento media 3,2 veces mayor que OpenSearch FAISS.

Retiro @ 10 - Detallado

Comparación detallada de latencias de recall@10 Elasticsearch BBQ vs Opensearch FAISS
Comparación detallada de recall@10 rendimiento Elasticsearch BBQ vs Opensearch FAISS.

tarea

latencia.media

rendimiento.mean

avg_recall

Elasticsearch-9.0-BBQ

10-100-100

11.70

513.58

0.89

Elasticsearch-9.0-BBQ

10-1000-100

27.33

250.55

0.95

Elasticsearch-9.0-BBQ

10-1500-1500

35.93

197.26

0.95

Elasticsearch-9.0-BBQ

10-200-200

13.33

456.16

0.92

Elasticsearch-9.0-BBQ

10-2000-2000

44.27

161.40

0.95

Elasticsearch-9.0-BBQ

10-40-40

10.97

539.94

0.84

Elasticsearch-9.0-BBQ

10-50-50

11.00

535.73

0.85

Elasticsearch-9.0-BBQ

10-500-500

19.52

341.45

0.93

Elasticsearch-9.0-BBQ

10-750-750

22.94

295.19

0.94

OpenSearch-2.19-faiss

10-100-100

35.59

200.61

0.94

OpenSearch-2.19-faiss

10-1000-1000

156.81

58.30

0.96

OpenSearch-2.19-faiss

10-1500-1500

181.79

42.97

0.96

OpenSearch-2.19-faiss

10-200-200

47.91

155.16

0.95

OpenSearch-2.19-faiss

10-2000-2000

232.14

31.84

0.96

OpenSearch-2.19-faiss

10-40-40

27.55

249.25

0.92

OpenSearch-2.19-faiss

10-50-50

28.78

245.14

0.92

OpenSearch-2.19-faiss

10-500-500

79.44

97.06

0.96

OpenSearch-2.19-faiss

10-750-750

104.19

75.49

0.96

Recuperación @ 50 - simplificado

En ese nivel de recuperación, Elasticsearch BBQ es hasta 5 veces más rápido (4,2 veces más rápido en promedio) y tiene 3,9 veces más rendimiento en promedio que OpenSearch FAISS.

Comparación de rendimiento vectorial Recal @50 Elasticsearch BBQ vs Opensearch FAISS
Elasticsearch BBQ puede ser hasta 5 veces más rápido (4,2 veces más rápido de media) y tiene un rendimiento media 3,9 veces mayor que OpenSearch FAISS.

Resultados detallados - Recall @ 50

Recall@50 Resultados de latencia de Elasticsearch BBQ y Opensearch FAISS
Recall@50 Resultados del rendimiento de Elasticsearch BBQ y Opensearch FAISS

Tarea

Latencia media

Media de rendimiento

Retiro promedio

Elasticsearch-9.0-BBQ

50-1000-1000

25.71

246.44

0.95

Elasticsearch-9.0-BBQ

50-1200-1200

28.81

227.85

0.95

Elasticsearch-9.0-BBQ

50-150-150

13.43

362.90

0.90

Elasticsearch-9.0-BBQ

50-1500-1500

33.38

202.37

0.95

Elasticsearch-9.0-BBQ

50-200-200

12.99

406.30

0.91

Elasticsearch-9.0-BBQ

50-2000-2000

42.63

163.68

0.95

Elasticsearch-9.0-BBQ

50-250-250

14.41

373.21

0.92

Elasticsearch-9.0-BBQ

50-500-500

17.15

341.04

0.93

Elasticsearch-9.0-BBQ

50-750-750

31.25

248.60

0.94

OpenSearch-2.19-faiss

50-1000-1000

125.35

62.53

0.96

OpenSearch-2.19-faiss

50-1200-1200

143.87

54.75

0.96

OpenSearch-2.19-faiss

50-150-150

43.64

130.01

0.89

OpenSearch-2.19-faiss

50-1500-1500

169.45

46.35

0.96

OpenSearch-2.19-faiss

50-200-200

48.05

156.07

0.91

OpenSearch-2.19-faiss

50-2000-2000

216.73

36.38

0.96

OpenSearch-2.19-faiss

50-250-250

53.52

142.44

0.93

OpenSearch-2.19-faiss

50-500-500

78.98

97.82

0.95

OpenSearch-2.19-faiss

50-750-750

103.20

75.86

0.96

Retiro @ 100

En ese nivel de recuperación, Elasticsearch BBQ es hasta 5 veces más rápido (promedio 4,6 veces más rápido) y tiene 3,9 veces más rendimiento en promedio que OpenSearch FAISS.

Retirar los resultados de FAISS de @100 Elasticsearch BBQ VS Opensearch
Comparación de latencia y rendimiento FAISS en Elasticsearch BBQ y Opensearch

Resultados detallados - Recall @ 100

Resultados detallados de latencia - Retirada @ 100 Elasticsearch BBQ vs Opensearch FAISS
Resultados detallados de rendimiento - Recall @ 100 Elasticsearch BBQ vs Opensearch FAISS.

tarea

latencia.media

rendimiento.mean

avg_recall

Elasticsearch-9.0-BBQ

100-1000-1000

27.82

243.22

0.95

Elasticsearch-9.0-BBQ

100-1200-1200

31.14

224.04

0.95

Elasticsearch-9.0-BBQ

100-1500-1500

35.98

193.99

0.95

Elasticsearch-9.0-BBQ

100-200-200

14.18

403.86

0.88

Elasticsearch-9.0-BBQ

100-2000-2000

45.36

159.88

0.95

Elasticsearch-9.0-BBQ

100-250-250

14.77

433.06

0.90

Elasticsearch-9.0-BBQ

100-300-300

14.61

375.54

0.91

Elasticsearch-9.0-BBQ

100-500-500

18.88

340.37

0.93

Elasticsearch-9.0-BBQ

100-750-750

23.59

285.79

0.94

OpenSearch-2.19-faiss

100-1000-1000

142.90

58.48

0.95

OpenSearch-2.19-faiss

100-1200-1200

153.03

51.04

0.95

OpenSearch-2.19-faiss

100-1500-1500

181.79

43.20

0.96

OpenSearch-2.19-faiss

100-200-200

50.94

131.62

0.83

OpenSearch-2.19-faiss

100-2000-2000

232.53

33.67

0.96

OpenSearch-2.19-faiss

100-250-250

57.08

131.23

0.87

OpenSearch-2.19-faiss

100-300-300

62.76

120.10

0.89

OpenSearch-2.19-faiss

100-500-500

84.36

91.54

0.93

OpenSearch-2.19-faiss

100-750-750

111.33

69.95

0.94

Mejoras en el asado

BBQ recorrió un largo camino desde su primer lanzamiento. En Elasticsearch 8.16, en aras de la comparación, incluimos una ejecución de referencia de 8.16 junto con la actual, y podemos ver cómo la recuperación y la latencia mejoraron desde entonces.

Las mejoras en la recuperación de latencia de Elasticsearch 9.0 BBQ se compararon con Elasticsearch 8.16 BBQ

En Elasticsearch 8.18 y 9.0, reescribimos el algoritmo central para cuantificar los vectores. Entonces, si bien BBQ en 8.16 fue bueno, las versiones más nuevas son aún mejores. Puedes leer sobre esto aquí y aquí. En resumen, cada vector se cuantifica individualmente a través de cuantiles escalares optimizados. Como resultado, los usuarios se benefician de una mayor precisión en la búsqueda vectorial sin comprometer el rendimiento, lo que hace que la recuperación vectorial de Elasticsearch sea aún más poderosa.

Conclusión

En esta comparación de rendimiento entre Elasticsearch BBQ y OpenSearch FAISS, Elasticsearch supera significativamente a OpenSearch para la búsqueda vectorial, logrando velocidades de consulta hasta 5 veces más rápidas y un rendimiento 3,9 veces mayor en promedio en varios niveles de recuperación.

Los hallazgos clave incluyen:

  • Recall@10: Elasticsearch BBQ es hasta 5 veces más rápido (3,9 veces más rápido en promedio) y tiene 3,2 veces más rendimiento en promedio en comparación con OpenSearch FAISS.

  • Recall@50: Elasticsearch BBQ es hasta 5 veces más rápido (4,2 veces más rápido en promedio) y tiene 3,9 veces más rendimiento en promedio en comparación con OpenSearch FAISS.

  • Recall@100: Elasticsearch BBQ es hasta 5 veces más rápido (4,6 veces más rápido en promedio) y tiene 3,9 veces más rendimiento en promedio en comparación con OpenSearch FAISS.

Estos resultados resaltan los beneficios de eficiencia y rendimiento de Elasticsearch BBQ, particularmente en escenarios de búsqueda vectorial de alta dimensión. La técnica Better Binary Quantization (BBQ), introducida en Elasticsearch 8.16, proporciona una reducción sustancial de la memoria (~95%) al tiempo que mantiene una alta calidad de clasificación, lo que la convierte en una opción superior para aplicaciones de búsqueda vectorial a gran escala.

En Elastic, estamos innovando incansablemente para mejorar Apache Lucene y Elasticsearch para proporcionar la mejor base de datos vectorial para casos de uso de búsqueda y recuperación, incluida RAG (Retrieval Augmented Generation). Nuestros avances recientes aumentaron significativamente el rendimiento, haciendo que la búsqueda vectorial sea más rápida y eficiente en cuanto al espacio que antes, basar en las ganancias de Lucene 10. Este blog es otra ilustración de esa innovación.

Contenido relacionado

LINQ a Elasticsearch ES|QL: escribir en C#, buscar en Elasticsearch

Florian Bernd

Mejorando las capacidades de los chatbots con PLN y búsqueda vectorial en Elasticsearch

Priscilla Parodi

Elasticsearch vs. OpenSearch: Comparación del rendimiento de búsqueda vectorial

Ugo Sangiorgi

Plagio por IA: detección de plagio con Elasticsearch

Priscilla Parodi

Técnicas avanzadas de RAG parte 2: Consultas y pruebas

Han Xiang Choong

¿Estás listo para crear experiencias de búsqueda de última generación?

No se logra una búsqueda suficientemente avanzada con los esfuerzos de uno. Elasticsearch está impulsado por científicos de datos, operaciones de ML, ingenieros y muchos más que son tan apasionados por la búsqueda como tú. Conectemos y trabajemos juntos para crear la experiencia mágica de búsqueda que te dará los resultados que deseas.

Pruébalo tú mismo