Alternativa a EAV para campos dinámicos en un almacén de datos de esquema en estrella


13

Necesito admitir campos y valores dinámicos en un gran datawarehouse para almacenar el registro de solicitudes de API, mi caso de usuario es que necesito almacenar todas las cadenas de consulta de solicitudes de API y poder realizar consultas en el futuro (por lo que no es solo almacenamiento, así que no puedo usar blob para ellos)

p.ej http://example.com/?action=test&foo=abc&bar=def...

Necesito almacenar todas las field => valueasignaciones, es decir (action => test), (foo => abc), (bar => def), y dado que el campo es tan dinámico, la única solución que he encontrado es usar Entity-Attribute-Value, sin embargo, la gente sigue diciendo que es un diseño muy malo.

Entonces, considere mi caso de uso anterior, ¿cuál sería una alternativa adecuada al EAV?

Mi esquema actual usando KAV

  1. Tabla requests
    (id, timestamp, uri)
    por ejemplo(1, 149382220, '/')

  2. Tabla params
    (request_id, key, value)
    por ejemplo(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

¿Alguna sugerencia?

Actualización: ejecutamos el almacén en AWS RedShift


2
¿Qué hay de malo en probar lo que estás sugiriendo en una base de datos de desarrollo? Además, ¿estás hablando de SQL Server? La etiqueta sql es bastante amplia.
Max Vernon,

Actualicé mi pregunta
Howard

1
¿Qué DBMS estás usando? Algunos tienen capacidades de indexación de texto bastante buenas, por lo que no descartaría usar un campo de "texto largo" para almacenar solicitudes. Dicho esto, no tendría problemas para usar el modelo que propone. Si bien EAV en sentido estricto, solo se usa para este propósito muy específico. Una vez más, una vez dicho eso, ¿qué tipo de consultas necesitas para poder hacer? Intente escribir estas consultas en este modelo para ver si funciona para usted.
Colin 't Hart

1
¿Qué RDBMS estás usando? SQLNo es lo suficientemente específico. Te han preguntado dos veces. Soy el tercero
Erwin Brandstetter

2
Desde RedShift se basa en PostgreSQL, me gustaría tratar de utilizar el hstoreo jsonlos tipos de datos (o jsonbsi / cuando "actualizar" a 9.4).
Colin 't Hart

Respuestas:


11

Puedo pensar en tres soluciones: EAV, XML y columnas dispersas. Este último es específico del proveedor y puede no serle útil.

Cualquiera que sea el método que elija, puede considerar almacenar los datos de la solicitud original en un formato sin formato, en una tabla o archivo sin formato. Le facilitará probar nuevas formas de almacenar los datos, le permitirá volver a cargar los datos si descubre un error con la forma en que analiza sus solicitudes, y ofrecerá oportunidades para analizar las solicitudes API utilizando el procesamiento por lotes o "big data" herramientas si encuentra que su almacén de datos no puede manejar eficientemente los datos.

Consideraciones de EAV

EAV / KVS, como lo describió anteriormente, es probable que sea la implementación más sencilla.

Desafortunadamente, también será muy costoso: para obtener cualquier tipo de consultas eficientes sobre las claves de uso común, necesitará tener índices en la columna de claves, que podrían fragmentarse mucho. Consultar claves particulares sería extremadamente costoso.

Es posible que pueda reducir el costo de la indexación o los escaneos de índices al admitir su tienda EAV con vistas materializadas (muchos proveedores lo respaldan) para consultar claves o valores que le interesan.

XML

La mayoría de los sistemas de bases de datos empresariales ofrecen un manejo XML muy maduro, que incluye validación, indexación y consultas sofisticadas.

Cargar la solicitud API en la base de datos como XML proporcionaría una tupla por solicitud, lo que lógicamente podría ser un poco más aceptable para usted que tener un número desconocido de filas en una tabla EAV.

Si esto es eficiente dependería mucho de su proveedor RDBMS y su implementación.

¡El mayor inconveniente es que esta es probablemente la única forma de administrar datos que es más complicada que la manipulación de cadenas de la solicitud original!

Columnas dispersas / mesas tradicionales

Es posible que pueda cargar sus datos en una estructura de tabla tradicional, con una columna por clave.

La función Columnas dispersas de SQL Server es una gran alternativa a una tienda EAV. Una tabla con columnas dispersas se comporta de manera muy similar a una tabla normal, excepto que puede tener hasta 30,000 columnas, y los valores NULL en columnas dispersas no consumen espacio en la tabla.

Combinarlos con índices filtrados (otra característica específica de SQL Server) puede proporcionar una alternativa extremadamente eficiente a un almacén EAV si consulta con frecuencia un par de columnas y / o valores específicos.

El uso de una tabla tradicional con otros proveedores puede ser viable: IBM admite más de 700 columnas por tabla y Oracle alrededor de 1000, y características como la compresión o el tratamiento de Oracle de los valores nulos finales pueden significar que puede almacenar sus datos API de manera bastante eficiente.

La desventaja obvia de este enfoque es que a medida que agrega nuevas claves a su API, necesitará ajustar su esquema en consecuencia.


2
En PostgreSQL No recomendaría XML pero o hstoreo json. En los próximos 9.4 jsonbsería mi recomendación.
Colin 't Hart

Realmente me gusta esta respuesta con los pros contras y la explicación de cada uno. Muy informativo: definitivamente aprecio la información de Columnas dispersas. Me gustaría un ejemplo de EAV utilizando el enfoque de columna dispersa.
StixO

9

EAV no es un mal diseño, per se, es simplemente un diseño que requiere una buena cantidad de previsión y puede ser forjado con problemas de rendimiento a medida que aumenta la cantidad de datos. Puede ser que para su sistema funcione bien.

Cuando diseñé un sistema para almacenar cadenas de consulta, no tenía idea de antemano en qué campos estaría interesado. Creé una tabla para almacenar la cadena de consulta en formato binario serializado y construí un sistema que me permitió dividir la consulta. encadenar en sus piezas componentes una vez que supiera las piezas que me interesaban. A partir de ahí, creé un conjunto de tablas; uno para los conjuntos de datos comúnmente contenidos dentro de la cadena de consulta.

Por ejemplo, eventualmente tuve una tabla para datos de referencia, una para datos de solicitud de destino y otra para elementos relacionados con el usuario, como la consulta de búsqueda que ingresaron.

Encontré la capacidad de almacenar toda la cadena de consulta en una sola tabla como un blob, mientras que la capacidad de dividir ese blob en el futuro satisfizo muy bien mis necesidades.


1
Tanto en la pregunta como en la respuesta BLOBse usa el término que significa Objeto binario largo. Preferiría usar un CLOB(Objeto largo de caracteres) o algo parecido texten PostgreSQL, ya que estamos hablando de caracteres y no de datos binarios.
Colin 't Hart

2
Usé un campo binario ya que en realidad serialicé todo el objeto de sesión y almacené todo en la base de datos.
Max Vernon
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.