El modelado de datos en Elasticsearch no es tan obvio como cuando se trata de bases de datos relacionales. A diferencia de las bases de datos relacionales tradicionales que dependen de la normalización de datos y uniones SQL, Elasticsearch requiere enfoques alternativos para gestionar las relaciones.
Existen cuatro soluciones alternativas comunes para gestionar relaciones en Elasticsearch:
Uniones del lado de la aplicación
Desnormalización de datos
Tipos de campos anidados y consultas anidadas
Relaciones entre padres e hijos
En este blog, analizaremos cómo puede diseñar su modelo de datos para manejar relaciones utilizando el tipo de campo anidado y las relaciones padre-hijo. Cubriremos la arquitectura, las implicaciones de rendimiento y los casos de uso de estas dos técnicas.
Elasticsearch admite estructuras anidadas, donde los objetos pueden contener otros objetos. Los tipos de campos anidados son objetos JSON dentro del documento principal, que pueden tener sus propios campos y tipos distintos. Estos objetos anidados se tratan como documentos ocultos separados a los que solo se puede acceder mediante una consulta anidada.
Los tipos de campos anidados son adecuados para relaciones en las que la integridad de los datos, el estrecho acoplamiento y la estructura jerárquica son importantes. Estas incluyen relaciones uno a uno y uno a muchos donde hay una entidad principal. Por ejemplo, representar a una persona y sus múltiples direcciones y números de teléfono en un solo documento.
Con los tipos de campos anidados, Elasticsearch almacena el documento completo, así como los objetos principales y anidados, en un único bloque y segmento de Lucene. Esto puede dar como resultado velocidades de consulta más rápidas ya que la relación está contenida en un documento.
Veamos un ejemplo de una publicación de blog con comentarios. Queremos anidar los comentarios debajo de la publicación del blog para que puedan consultarse juntos fácilmente en el mismo documento.
{ "post_id": "1", "title": "Introduction to Elasticsearch Data Modeling", "content": "Exploring various data modeling options in Elasticsearch.", "comments": [ { "comment_id": "101", "text": "Great overview of data modeling!" }, { "comment_id": "102", "text": "Looking forward to more content." } ] }
Los beneficios de las relaciones de objetos anidados incluyen:
Ineficiencia de la actualización : las actualizaciones, inserciones y eliminaciones de cualquier parte de un documento con objetos anidados requieren volver a indexar todo el documento, lo que puede consumir mucha memoria, especialmente si los documentos son grandes o las actualizaciones son frecuentes.
Rendimiento de consultas con campos anidados grandes : si tiene documentos con campos anidados particularmente grandes, esto puede tener implicaciones en el rendimiento. Esto se debe a que la solicitud de búsqueda recupera el documento completo.
Múltiples niveles de anidamiento pueden volverse complejos : ejecutar consultas en estructuras anidadas con múltiples niveles aún puede volverse complejo. Esto se debe a que las consultas pueden involucrar consultas anidadas dentro de consultas anidadas, lo que genera código menos legible.
En el mapeo padre-hijo, los documentos se organizan en tipos padre e hijo. Cada documento secundario tiene una asociación directa con un documento principal. Esta relación se establece a través de un valor de campo específico en el documento secundario que coincide con el ID del padre. El modelo padre-hijo adopta un enfoque descentralizado donde los documentos padre-hijo existen de forma independiente.
Las uniones entre padres e hijos son adecuadas para relaciones de uno a muchos o de muchos a muchos entre entidades. Imagine una aplicación en la que desea crear relaciones entre empresas y contactos y desea buscar empresas y contactos, así como contactos de empresas específicas.
Elasticsearch hace que las uniones entre padres e hijos sean eficientes al realizar un seguimiento de qué padres están conectados y qué hijos y al hacer que ambas entidades residan en el mismo fragmento. Al localizar la operación de unión, Elasticsearch evita la necesidad de una comunicación extensa entre fragmentos, lo que puede ser un cuello de botella en el rendimiento.
Tomemos el ejemplo de una relación entre padres e hijos para publicaciones y comentarios de blogs. Cada entrada del blog, es decir, la de los padres, puede tener varios comentarios, es decir, los hijos. Para crear la relación padre-hijo, indexemos los datos de la siguiente manera:
PUT my-index-000001 { "mappings": { "properties": { "post_id": { "type": "keyword" }, "post_id": { "type": "join", "relations": { "post": "comment" } } } } }
Un documento principal sería una publicación similar a esta:
{ "post_id": "1", "title": "Introduction to Elasticsearch Data Modeling", "content": "Exploring various data modeling options in Elasticsearch." }
El documento secundario sería entonces un comentario que contiene el post_id que lo vincula con su documento principal.
{ "comment_id": "101", "text": "Great overview of data modeling!", "post_id": "1" }
Los beneficios del modelado entre padres e hijos incluyen:
Se asemeja al modelo de datos relacionales : en las relaciones padre-hijo, los documentos padre e hijo están separados y están vinculados por una identificación principal única. Esta configuración se acerca más a un modelo de base de datos relacional y puede resultar más intuitiva para quienes estén familiarizados con dichos conceptos.
Eficiencia de actualización : los documentos secundarios se pueden agregar, modificar o eliminar sin afectar el documento principal u otros documentos secundarios. Esto es particularmente beneficioso cuando se trata de una gran cantidad de documentos secundarios que requieren actualizaciones frecuentes. Tenga en cuenta que asociar un documento secundario con un padre diferente es un proceso más complejo ya que el nuevo padre puede estar en otro fragmento.
Más adecuado para niños heterogéneos : dado que los documentos secundarios se almacenan por separado, pueden ser más eficientes en cuanto a memoria y almacenamiento, especialmente en los casos en los que hay muchos documentos secundarios con diferencias de tamaño significativas.
Los inconvenientes de las relaciones entre padres e hijos incluyen:
Consultas costosas y lentas : unir documentos a través de índices separados agrega trabajo computacional durante la ejecución de la consulta, lo que nuevamente afecta el rendimiento. Elasticsearch señala que las consultas entre padres e hijos pueden ser entre 5 y 10 veces más lentas que las consultas de objetos anidados.
Gastos generales de mapeo : las relaciones entre padres e hijos pueden consumir más memoria y recursos de caché. Elasticsearch mantiene un mapa de relaciones entre padres e hijos, que puede crecer y consumir una cantidad significativa de memoria, especialmente con un gran volumen de documentos.
Gestión del tamaño de los fragmentos : dado que tanto los documentos principales como los secundarios residen en el mismo fragmento, existe un riesgo potencial de distribución desigual de los datos en todo el clúster. Algunos fragmentos pueden llegar a ser significativamente más grandes que otros, especialmente si hay documentos principales con muchos hijos. Esto puede generar desafíos en la gestión y ampliación del clúster de Elasticsearch .
Reindexación y mantenimiento del clúster : si necesita reindexar datos o cambiar la estrategia de fragmentación , la relación padre-hijo puede complicar este proceso. Deberá asegurarse de que se mantenga la integridad de la relación durante dichas operaciones. Las tareas rutinarias de mantenimiento del clúster, como el reequilibrio de fragmentos o las actualizaciones de nodos, pueden volverse más complejas. Se debe tener especial cuidado para garantizar que las relaciones entre padres e hijos no se interrumpan durante estos procesos.
Elastic , la compañía detrás de Elasticsearch, siempre recomendará que realice uniones del lado de la aplicación, desnormalización de datos y/u objetos anidados antes de seguir el camino de las relaciones padre-hijo.
La siguiente tabla proporciona un resumen de las características de los tipos de campos anidados y las consultas y las relaciones entre padres e hijos para comparar los enfoques de modelado de datos uno al lado del otro.
| Tipos de campos anidados y consultas anidadas | Relaciones entre padres e hijos |
---|---|---|
Definición | Anida un objeto dentro de otro objeto | Vincula documentos principales y secundarios |
Relaciones | Uno a uno, uno a muchos | Uno a muchos, muchos a muchos |
Velocidad de consulta | Generalmente más rápido que las relaciones padre-hijo ya que los datos se almacenan en el mismo bloque y segmento. | Generalmente es entre 5 y 10 veces más lento que los objetos anidados, ya que los documentos principal y secundario se unen en el momento de la consulta. |
Flexibilidad de consulta | Menos flexible que las consultas entre padres e hijos, ya que limita el alcance de la consulta dentro de los límites de cada objeto anidado. | Ofrece más flexibilidad en las consultas, ya que los documentos principales o secundarios se pueden consultar juntos o por separado. |
Actualizaciones de datos | La actualización de objetos anidados requirió la reindexación de todo el documento | Actualizar documentos secundarios es más fácil ya que no es necesario volver a indexar todos los documentos. |
Gestión | Gestión más sencilla ya que todo está contenido en un único documento | Más complejo de administrar debido a la indexación separada y al mantenimiento de relaciones entre los documentos principales y secundarios. |
Casos de uso | Almacene y consulte datos complejos con múltiples niveles de jerarquía | Relaciones en las que hay pocos padres y muchos hijos, como productos y reseñas de productos. |
Si bien Elasticsearch proporciona varias soluciones para las uniones de estilo SQL , incluidas consultas anidadas y relaciones entre padres e hijos, está establecido que estos modelos no se escalan bien. Al diseñar aplicaciones a escala, puede tener sentido considerar un enfoque alternativo con capacidades de unión SQL nativas, Rockset .
Rockset es una base de datos de búsqueda y análisis diseñada para búsquedas SQL, agregaciones y uniones de cualquier dato, incluidos datos JSON profundamente anidados. A medida que los datos se transmiten a Rockset, se codifican en las estructuras de datos centrales de la base de datos que se utilizan para almacenar e indexar los datos para una recuperación rápida. Rockset indexa los datos de una manera que permite consultas rápidas, incluidas uniones, utilizando su optimizador de consultas basado en SQL. Como resultado, no se requiere un modelado de datos inicial para admitir uniones SQL.
Uno de los desafíos de Elasticsearch es cómo preservar la relación de manera eficiente cuando se actualizan los datos. Una de las razones es que Elasticsearch se basa en Apache Lucene, que almacena datos en segmentos inmutables, lo que hace que sea necesario volver a indexar todos los documentos. Rockset utiliza RocksDB, un almacén clave-valor de código abierto de Meta y creado para mutaciones de datos, para poder admitir de manera eficiente actualizaciones a nivel de campo sin necesidad de volver a indexar documentos completos.
Comparemos el enfoque de relación padre-hijo en Elasticsearch con una consulta SQL en Rockset.
En el ejemplo anterior de relación entre padres e hijos, modelamos publicaciones con múltiples comentarios creando dos tipos de documentos:
publicaciones o el tipo de documento principal
comentarios o los tipos de documentos secundarios
Usamos un identificador único, el ID del padre, para establecer la relación entre los documentos padre e hijo. En el momento de la consulta, utilizamos Elasticsearch DSL para recuperar comentarios de una publicación específica.
En Rockset, los datos que contienen publicaciones se almacenarían en una colección, una tabla en el mundo relacional, mientras que los datos que contienen comentarios se almacenarían en una colección separada. En el momento de la consulta, uniríamos los datos mediante una consulta SQL.
Aquí están los dos enfoques uno al lado del otro:
POST /blog/posts/1 { "title": "Elasticsearch Modeling", "content": "A post about data modeling in Elasticsearch" } POST /blog/comments/2?parent=1 { "text": "Great post!" } POST /blog/comments/3?parent=1 { "text": "I learned a lot from this." }
Para recuperar una publicación por su título y todos sus comentarios, deberá crear una consulta de la siguiente manera.
GET /posts/_search { "query": { "bool": { "must": [ { "match": { "title": "Exploring Elasticsearch Models" } } ] } }, "inner_hits": { "_source": ["text"], "name": "comments", "path": "comments" } }
Para luego consultar estos datos, sólo necesita escribir una consulta SQL simple.
SELECT p.title, p.content, c.text FROM posts p JOIN comments c ON p.post_id = c.post_id WHERE p.post_id = 1;
Si tiene varios conjuntos de datos que deben unirse para su aplicación, Rockset es más sencillo y escalable que Elasticsearch. También simplifica las operaciones, ya que no necesita remodelar sus datos, administrar actualizaciones ni reindexar operaciones.
Este blog proporcionó una descripción general de los tipos de campos anidados, las consultas anidadas y las relaciones entre padres e hijos en Elasticsearch con el objetivo de ayudarlo a determinar el mejor enfoque de modelado de datos para su carga de trabajo.
Los tipos de campos anidados y las consultas son útiles para relaciones uno a uno o uno a muchos donde la relación se mantiene dentro de un solo documento. Este se considera un enfoque más simple y escalable para la gestión de relaciones.
El modelo de relación padre-hijo es más adecuado para relaciones de uno a muchos o de muchos a muchos, pero presenta una mayor complejidad, especialmente porque las relaciones deben estar contenidas en un fragmento específico.
Si uno de los requisitos principales de su aplicación es modelar relaciones, puede tener sentido considerar Rockset. Rockset simplifica el modelado de datos y ofrece un enfoque más escalable para la gestión de relaciones mediante uniones SQL. Puede comparar y contrastar el rendimiento de Elasticsearch y Rockset iniciando una prueba gratuita con $300 en créditos hoy.