Maneras de actualizar documentos en Elasticsearch

La búsqueda elástica es un motor de búsqueda y análisis de código abierto basado en Apache Lucene. Al desarrollar aplicaciones a partir de datos de captura de datos modificados (CDC) utilizando Elasticsearch, es importante diseñar el sistema para manejar actualizaciones o modificaciones frecuentes de los documentos existentes en un índice.

En esta publicación, exploraremos las diversas opciones disponibles para las actualizaciones, que incluyen actualizaciones completas, actualizaciones parciales y actualizaciones programadas. También analizaremos qué sucede internamente en Elasticsearch al modificar un documento y cómo las actualizaciones frecuentes afectan la utilización de la CPU en el sistema.

Ejemplo de aplicación con actualizaciones frecuentes

Para comprender mejor los escenarios que implican actualizaciones frecuentes, consideremos una aplicación de búsqueda para un servicio de transmisión de video como Netflix. Cuando un usuario busca un programa, como "thriller político", se le presentan resultados relevantes basados en palabras clave y otros metadatos.

Veamos un ejemplo de documento en Elasticsearch del programa "House of Cards":

Contenido incrustado: https://gist.github.com/julie-mills/1b1b0f87dcca601a6f819d3086db4c27

La configuración de búsqueda en Elasticsearch se puede personalizar para utilizar los campos name y description como campos de texto completo. El campo views, que almacena el número de vistas por título, puede ser aprovechado para mejorar el contenido y clasificar los programas más populares en una posición más alta. El campo views se incrementa cada vez que un usuario ve un episodio de un programa o una película.

Cuando se aplica esta configuración de búsqueda en una aplicación a la escala de Netflix, la cantidad de actualizaciones realizadas puede superar fácilmente los millones por minuto, como se indica en el Informe de compromiso de Netflix. Según el informe, los usuarios vieron ~100 mil millones de horas de contenido en Netflix entre enero y julio. Suponiendo un tiempo de visualización promedio de 15 minutos por episodio o película, el número de visualizaciones por minuto alcanza un promedio de 1,3 millones. Con la configuración de búsqueda mencionada anteriormente, cada vista requeriría una actualización a escala de millones.

Muchas aplicaciones de búsqueda y análisis pueden experimentar actualizaciones frecuentes, especialmente cuando se basan en datos de CDC.

Realización de actualizaciones en Elasticsearch

Profundicemos en un ejemplo general de cómo llevar a cabo una actualización en Elasticsearch con el siguiente código:

Contenido incrustado: https://gist.github.com/julie-mills/c2bc1b4d32198fbc9df0975cd44546c0

Actualizaciones completas vs. actualizaciones parciales en Elasticsearch

Al realizar una actualización en Elasticsearch, puede emplear el API de índice para reemplazar un documento existente o el API de actualización para llevar a cabo una actualización parcial de un documento.

El API de índice recupera el documento completo, realiza cambios en él y luego lo vuelve a indexar. Por otro lado, con el API de actualización, simplemente se envían los campos que se desean modificar, en lugar de todo el documento. Aunque esto aún implica que el documento se reindexe, se minimiza la cantidad de datos enviados a través de la red. El API de actualización es especialmente útil en situaciones en las que el tamaño del documento es considerable y enviarlo completo a través de la red sería un proceso largo.

Veamos cómo funcionan tanto el API de índice como el API de actualización usando código Python.

Actualizaciones completas utilizando el API de índice en Elasticsearch

Contenido incrustado: https://gist.github.com/julie-mills/d64019542768baad2825e2f9c6bf94e6

Como se observa en el código anterior, el API de índice requiere dos llamadas separadas a Elasticsearch, lo que puede resultar en un rendimiento más lento y una mayor carga en su clúster.

Actualizaciones parciales mediante el uso del API de actualización en Elasticsearch

Las actualizaciones parciales hacen uso internamente del API de reindexación pero están configuradas para requerir solamente una llamada a la red para un mejor rendimiento.

Contenido incrustado: https://gist.github.com/julie-mills/49125b47699cd0b6c2b2a0c824e8e2c0

Se puede emplear el API de actualización en Elasticsearch para actualizar el recuento de vistas, sin embargo, por sí solo, el API de actualización no permite incrementar dicho recuento basándose en el valor previo. Esto se debe a que se requiere el recuento de vistas anterior para establecer el nuevo valor de vistas.

Veamos cómo abordar esta cuestión usando un lenguaje de programación potente, Painless.

Actualizaciones parciales utilizando scripts Painless en Elasticsearch

Painless es un lenguaje de programación diseñado para Elasticsearch y se puede utilizar para consultas y cálculos de agregación, condicionales complejos, transformaciones de datos, entre otros. Painless también habilita el uso de scripts en consultas de actualización para modificar documentos según una lógica compleja.

En el siguiente ejemplo, empleamos un script Painless para llevar a cabo una actualización en una única llamada API e incrementar el recuento de vistas nuevos basándonos en el valor previo del recuento de vistas.

Contenido incrustado: https://gist.github.com/julie-mills/50da3261ae1866bd95734544c98b58af

El script Painless es bastante fácil de comprender, simplemente incrementa el recuento de vistas en 1 para cada documento.

Actualizar un objeto anidado en Elasticsearch

Los objetos anidados en Elasticsearch son una estructura de datos que permite la indexación de matrices de objetos como documentos separados dentro de un solo documento principal. Los objetos anidados son útiles cuando se trata de datos complejos que naturalmente forman una estructura anidada, como objetos dentro de otros objetos. En un documento típico de Elasticsearch, las matrices de objetos se aplana, pero al utilizar el tipo de datos anidados se permite indexar y consultar cada objeto de la matriz de forma independiente.

También se pueden emplear scripts simples para actualizar objetos anidados en Elasticsearch.

Agregar un nuevo campo en Elasticsearch

SePuedes incluir un campo adicional en un documento en Elasticsearch mediante una operación de indexación.

Es posible actualizar parcialmente un documento existente con el nuevo campo utilizando la API de actualización. Cuando el mapeo dinámico está activado en el índice, agregar un nuevo campo es sencillo. Solo necesitas indexar un documento que contenga ese campo, y Elasticsearch se encargará automáticamente de asignar y agregar el nuevo campo.

Si el mapeo dinámico está desactivado en el índice, deberás utilizar la API de mapeo para la actualización. Abajo se muestra un ejemplo de cómo actualizar el mapeo de un índice al añadir un campo de "categoría" al índice de películas.

Contenido incrustado: https://gist.github.com/julie-mills/b83e89341f4db23e021df4ca6b5ed644

Actualizaciones en Elasticsearch bajo la superficie

Aunque el código puede parecer simple, Elasticsearch realiza una gran cantidad de trabajo pesado internamente para llevar a cabo estas actualizaciones debido a que los datos se almacenan en segmentos inmutables. Por lo tanto, Elasticsearch no puede simplemente actualizar un documento en su lugar. La única forma de realizar una actualización es reindexar todo el documento, independientemente de la API utilizada.

Elasticsearch utiliza Apache Lucene como motor subyacente. Un índice de Lucene consta de uno o varios segmentos. Cada segmento es una estructura de índice autocontenida e inmutable que representa una parte del índice en general. Al agregar o actualizar documentos, se generan nuevos segmentos de Lucene y los documentos antiguos se marcan para su eliminación temporal. Con el tiempo, a medida que se añaden nuevos documentos o se actualizan los existentes, se pueden acumular múltiples segmentos. Para optimizar la estructura del índice, Lucene fusiona de forma periódica segmentos más pequeños en segmentos más grandes.

Actualizaciones en Elasticsearch son esencialmente inserciones

Dado que cada actualización implica un proceso de reindexación, todas las actualizaciones en realidad equivalen a inserciones con eliminaciones temporales.

Hay implicaciones de costos al tratar una actualización como una inserción. Por un lado, la eliminación temporal de datos implica que los datos antiguos permanezcan durante un tiempo, lo que infla el almacenamiento y la memoria del índice. Las operaciones de eliminación temporal, reindexación y recolección de basura también conllevan un alto costo en términos de uso de la CPU, costos que se acumulan al repetir estas operaciones en todas las réplicas.

A medida que tu producto crece y los datos evolucionan, las actualizaciones pueden volverse más complejas. Para mantener el rendimiento de Elasticsearch, es necesario actualizar los fragmentos, analizadores y tokenizadores en tu clúster, lo que requiere la reindexación de todo el clúster. Para entornos de producción, esto conlleva la necesidad de configurar un nuevo clúster y migrar todos los datos. La migración de clústeres es un proceso que requiere tiempo y es propenso a errores, por lo que no debe tomarse a la ligera.

Actualizaciones en Elasticsearch

Aunque las operaciones de actualización en Elasticsearch pueden parecer simples, existen tareas operativas complejas que se llevan a cabo en segundo plano. Cada actualización requiere la recreación y reindexación completa del documento. Para aplicaciones con actualizaciones frecuentes, este proceso puede volverse costoso rápidamente, como se menciona en el ejemplo de Netflix, donde se realizan millones de actualizaciones por minuto. Se recomienda realizar actualizaciones por lotes mediante el uso del [API masiva](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html) para minimizar la latencia en tu carga de trabajo, o buscar alternativas ante actualizaciones frecuentes en Elasticsearch.

Rockset, una base de datos de búsqueda y análisis construida en la nube, representa una alternativa a Elasticsearch. Construido sobre [RocksDB](https://rockset.com/blog/rocksdb-is-eating-the-database-world/), un almacén de valores clave conocido por su capacidad de mutabilidad, Rockset puede llevar a cabo actualizaciones in situ de documentos. Esto implica actualizar y reindexar solo los valores de campos individuales en lugar de todo el documento. Si estás interesado en comparar el rendimiento entre Elasticsearch y Rockset para cargas de trabajo con muchas actualizaciones, puedes iniciar una [prueba gratuita de Rockset](https://rockset.com/create/) con $300 en créditos.

¿Nos apoyarás hoy?

Creemos que todos merecen entender el mundo en el que viven. Este conocimiento ayuda a crear mejores ciudadanos, vecinos, amigos y custodios de nuestro planeta. Producir periodismo explicativo y profundamente investigado requiere recursos. Puedes apoyar esta misión haciendo una donación económica a Gelipsis hoy. ¿Te sumarás a nosotros?

Suscríbete para recibir nuestro boletín:

Recent Articles

Related Stories

DEJA UN COMENTARIO

Por favor ingrese su comentario!
Por favor ingrese su nombre aquí