2009-04-05 12 views
8

Agradecería algunas opiniones sobre una preocupación que tengo.Pregunta de diseño de base de datos

Tengo una tabla [usuario] en mi base de datos, con las cosas básicas que cabría esperar, como nombre de usuario, contraseña, etc ...

Esta aplicación requiere que el seguimiento de un gran número de atributos para cada usuario. Tanto es así, que probablemente me queden sin columnas (espacio de almacenamiento de fila).

Tengo la tentación de agregar una tabla UserProperties con las columnas UserID, PropertyKey y PropertyValue. Este enfoque se ajusta bien a los requisitos.

Mi preocupación es que si cada usuario tiene decir 100 propiedades, cuando la base de datos tiene un millón de usuarios en ella, tendremos 100,000,000 filas de propiedades.

Creo que con un índice agrupado en el UserID, ese acceso seguirá gritando rápido, y realmente está almacenando la misma cantidad de datos que con el enfoque de megacolumnas.

¿Alguna idea o idea sobre las preocupaciones de rendimiento? Ideas para un mejor diseño de DB?

Gracias!

ACTUALIZACIÓN:

En primer lugar, muchas gracias por todas las grandes respuestas!

He estado jugando con las posibilidades, y una cosa sigue molestándome. Necesito consultar sobre algunos de estos atributos con bastante frecuencia y, lo que es peor, estas consultas podrían incluir la búsqueda de todos los usuarios que coinciden con los criterios en hasta 10 de estos atributos al mismo tiempo.

Como resultado, me estoy inclinando ahora hacia el enfoque de megacolumnas, pero posiblemente dividiendo los datos en una (o más) tablas separadas, formando una relación de uno a uno en el ID de usuario.

Estoy usando LinqToSql, y si bien creo que las tablas con muchas columnas son poco elegantes, creo que teniendo en cuenta todos los desafíos y compensaciones, probablemente sea la correcta, pero todavía estoy ansioso por escuchar otras opiniones.

Respuesta

11

Lo que está describiendo es una base de datos Entity-Attribute-Value, que a menudo se usa para exactamente la situación que describes, datos escasos vinculados a una sola entidad.

Una tabla E-A-V es fácil de buscar. El problema no es encontrar filas, sino encontrar filas relacionadas.

Tener diferentes tablas para entidades diferentes proporciona modelado de dominio, pero también proporcionan una forma débil de metadatos. En E-A-V no hay tales abstracciones. (La analogía de Java con EAV sería declarar que los argumentos formales de todas las funciones eran de tipo Objeto, por lo que no obtendría ninguna comprobación de tipo)

Podemos buscar fácilmente las claves de la propiedad, pero no se agrupan estas propiedades llaves.

Wikipedia tiene un artículo muy bueno sobre E-A-V, pero léalo ahora: en su mayoría es obra de un autor y está programado para "mejorar".

+0

No podría estar más de acuerdo. El modelo Entidad-Relacional es poderoso una vez que lo manejas. Siento por el pobre tipo que hereda una base de datos con entidades aplanadas en pares de nombre/valor y tiene que hacer cara o cruz. –

3

El enfoque de la tabla UserProperties es cómo lo modelaría. Como sugirió, un índice agrupado en ID de usuario significará que las búsquedas de rango en ID de usuario serán rápidas (es decir, para todas las propiedades relacionadas con un solo usuario). También podría agregar un índice no agrupado en UserID y PropertyKey para selecciones de clave única de 2 valores por usuario.

1

Dudo que tenga tantos valores de datos de 1 a 1 en la tabla Usuarios que se quedará sin espacio de filas. Solo debería descargar de 1 a muchos valores en otra tabla, utilizando la ID de usuario como clave externa. Me parece poco probable que su tabla de usuarios requiera tantos campos VARCHAR() que de alguna manera no puedan convertirse en FK a partir de una tabla maestra de valores. ¿Qué tipo de atributos de usuario estás manteniendo?

1

¿Alguna manera de agrupar lógicamente las propiedades? Es posible que no siempre necesites acceder a todas las propiedades. Además, si están lógicamente agrupados, será más fácil entender qué propiedades están disponibles, dónde encajan las nuevas propiedades, etc. ...

Las agrupaciones pueden tener una relación de uno a uno o de uno a muchos con el usuario ...

+0

agrupación podría agregarse agregando un groupID a la tabla UserProperties –

+0

Mitch, no creo que ese fuera el punto. Creo que fue para reducir el tamaño de la mesa. – mpen

+0

Los índices 'derechos' hacen que el tamaño de la tabla sea menor al de un problema –

1

Hemos implementado la estrategia UserProperties en varios proyectos.Este es un patrón común y con los índices apropiados nunca nos hemos encontrado con un problema de rendimiento.

Otra ventaja es que puede tener dos o más tablas de propiedades si es necesario para administrar el acceso del usuario. Por ejemplo, las propiedades generales podrían estar en la tabla PublicUserProps, mientras que la información sensible (no sé lo que está almacenando, pero ssn, información de nómina, etc.) podría estar en una tabla ControlledUserProps a la que solo algunos usuarios habrían leído o editado derechos.

1

Me gusta el enfoque meta-tabla que Mitch Wheat y usted describieron. Pero si tiene unos pocos campos que se usarán con más frecuencia que otros (como el nombre, etc.), entonces puede encontrar que tenerlos en la tabla de Usuario podría ser beneficioso y luego vincular la tabla de usuarios a las Propiedades del Usuario. Supongo que todo depende de los detalles exactos de su diseño.

+0

los índices correctos y el almacenamiento en caché deben ocuparse de cualquier problema de rendimiento relacionado con los datos de uso frecuente –

1

Unas pocas opciones que se me ocurren:

campos
  • bits: Puede almacenar muchos valores de allí y se puede añadir más campos, según sea necesario, o incluso utilizar una tabla separada
  • poner los ajustes más comunes en la tabla de usuario y la configuración que cada usuario puede no tener en una segunda tabla
  • solamente almacenar los ajustes que son diferentes de los predeterminados
1

dadas las limitaciones indicadas, no creo ¡Realmente tienes otra opción!

bien, se puede dividir los atributos del usuario a través de múltiples tablas que comparten el mismo ID de usuario como su clave principal (y del índice agrupado), pero esto puede o no puede mejorar el rendimiento

si sólo está hablando de 100 atributos , esto podría manejarse con una tabla (en MS-SQL max son 1023 columnas sin clave); si los atributos están escasamente ocupados, entonces una tabla de atributos de usuario puede ser potencialmente más eficiente en espacio (solo su profiler está seguro)

1

Creo que con un índice agrupado en el UserID, ese acceso todavía estará gritando rápido, y realmente está almacenando la misma cantidad de datos que con el enfoque de megacolumnas.

Creo que con una tabla de propiedades terminará almacenando mucho más de lo que realmente necesita.A saber, el índice adicional de la identificación del usuario, la columna de clave de propiedad y el hecho de que el valor de la propiedad deberá poder manejar valores de naturaleza genérica que dificulten la optimización.

Mi consejo es tratar de poner todo en una tabla y luego iniciarlo con algunos datos de prueba. SI no funciona, entonces podría ir por el camino de una solución de tabla múltiple o incluso una solución no-db (no son balas de plata después de todo).

7

Te recomiendo que consideres el enfoque conocido como partición vertical. Esto significa que sigue definiendo tablas con una clave de ID de usuario, puede llamarlas Usuario1, Usuario2, etc. Comience una nueva tabla cuando llegue al tamaño máximo de fila para su base de datos. El beneficio de este enfoque es que los valores siguen siendo verdaderos atributos de la base de datos. Esto terminará ahorrando tiempo al trabajar con estos datos, p. el enlace de datos.

La pregunta clave a responder es: ¿son realmente estos atributos? ¿Representan la estructura de la información que debe recopilar sobre el usuario? Si es así, la mejor manera de modelarlos es hacerlos columnas. La única razón por la que debe recurrir a la partición vertical es el límite de tamaño de fila de la base de datos.

Si, por otro lado, se necesita un sistema de atributos flexible, entonces, por supuesto, vaya con el sistema de clave de propiedad/valor de propiedad. Por ejemplo, si a los usuarios se les permitiera definir sus propios atributos dinámicamente, entonces definitivamente querrías el sistema clave/valor. Sin embargo, diría que la clave/valor no es la mejor manera si comprende la estructura de sus datos y ha identificado legítimamente cientos de atributos para los usuarios.

Como nota al margen, debo decir que debe cuestionar entidades con un gran número de atributos. Pueden ser válidos, pero también es bastante probable que te falten algunas entidades en el nivel conceptual. En otras palabras, todos estos atributos no están relacionados con el usuario per se, sino con alguna otra entidad relacionada con los usuarios.

Cuestiones relacionadas