Guardo varios detalles de usuario en mi base de datos MySQL. Originalmente, se configuró en varias tablas, lo que significa que los datos están vinculados con UserIds y se generan a través de llamadas a veces complicadas para mostrar y manipular los datos según sea necesario. Al configurar un nuevo sistema, casi tiene sentido combinar todas estas tablas en una gran tabla de contenido relacionado.
- ¿Será esto una ayuda o un obstáculo?
- ¿Consideraciones de velocidad al llamar, actualizar o buscar / manipular?
Aquí hay un ejemplo de algunas de las estructuras de mi tabla:
- usuarios: ID de usuario, nombre de usuario, correo electrónico, contraseña cifrada, fecha de registro, ip
- user_details: datos de cookies, nombre, dirección, detalles de contacto, afiliación, datos demográficos
- user_activity - contribuciones, última conexión, última visita
- user_settings - configuración de visualización del perfil
- user_interests: variables a las que se puede orientar publicidad
- user_levels - derechos de acceso
- user_stats - hits, recuentos
Editar: He votado a favor de todas las respuestas hasta ahora, todas tienen elementos que esencialmente responden a mi pregunta.
La mayoría de las tablas tienen una relación 1: 1 que fue la principal razón para desnormalizarlas.
¿Habrá problemas si la tabla abarca más de 100 columnas cuando es probable que una gran parte de estas celdas permanezcan vacías?
fuente
Respuestas:
Varias tablas ayudan de las siguientes formas / casos:
(a) si diferentes personas van a desarrollar aplicaciones que involucran diferentes tablas, tiene sentido dividirlas.
(b) Si desea otorgar diferentes tipos de autoridades a diferentes personas para diferentes partes de la recopilación de datos, puede ser más conveniente dividirlas. (Por supuesto, puede considerar la definición de vistas y darles la autorización correspondiente).
(c) Para mover datos a diferentes lugares, especialmente durante el desarrollo, puede tener sentido usar tablas que resulten en tamaños de archivo más pequeños.
(d) Una huella más pequeña puede brindarle comodidad mientras desarrolla aplicaciones sobre la recopilación de datos específicos de una sola entidad.
(e) Es una posibilidad: lo que pensaba que era un dato de valor único puede llegar a ser realmente valores múltiples en el futuro. por ejemplo, el límite de crédito es un campo de valor único a partir de ahora. Pero mañana, puede decidir cambiar los valores como (fecha de, fecha a, valor de crédito). Las tablas divididas pueden resultar útiles ahora.
Mi voto sería a favor de varias tablas, con datos debidamente divididos.
Buena suerte.
fuente
Combinar las tablas se llama desnormalizar.
Puede (o no) ayudar hacer algunas consultas (que hacen muchas
JOIN
s) para que se ejecuten más rápido a expensas de crear un infierno de mantenimiento.MySQL
es capaz de utilizar un únicoJOIN
método, a saberNESTED LOOPS
.Esto significa que para cada registro en la tabla conducida,
MySQL
ubica un registro coincidente en la tabla conducida en un bucle.Localizar un registro es una operación bastante costosa que puede tardar docenas de veces más que el escaneo de un registro puro.
Mover todos sus registros a una tabla le ayudará a deshacerse de esta operación, pero la tabla en sí aumenta de tamaño y la exploración de la tabla lleva más tiempo.
Si tiene muchos registros en otras tablas, el aumento de la exploración de la tabla puede sobrepasar los beneficios de la exploración secuencial de los registros.
El infierno de mantenimiento, por otro lado, está garantizado.
fuente
¿Son todas relaciones 1: 1? Quiero decir, si un usuario pudiera pertenecer a, digamos, diferentes niveles de usuario, o si los intereses de los usuarios están representados como varios registros en la tabla de intereses del usuario, entonces la fusión de esas tablas estaría fuera de discusión de inmediato.
Con respecto a las respuestas anteriores sobre la normalización, debe decirse que las reglas de normalización de la base de datos han ignorado por completo el rendimiento, y solo están mirando lo que es un diseño de base de datos ordenado. Eso es a menudo lo que quiere lograr, pero hay ocasiones en las que tiene sentido desnormalizar activamente en pos del rendimiento.
En general, diría que la pregunta se reduce a cuántos campos hay en las tablas y con qué frecuencia se accede a ellos. Si la actividad del usuario a menudo no es muy interesante, entonces podría ser una molestia tenerla siempre en el mismo registro, por razones de rendimiento y mantenimiento. Si se accede a algunos datos, como la configuración, por ejemplo, con mucha frecuencia, pero simplemente contienen demasiados campos, es posible que tampoco sea conveniente fusionar las tablas. Si solo está interesado en la ganancia de rendimiento, puede considerar otros enfoques, como mantener la configuración separada, pero guardarla en una variable de sesión propia para que no tenga que consultar la base de datos con mucha frecuencia.
fuente
3NF
normalización, así que benefíciese de una segunda tabla para resolver eso, pero eso no parece ser a lo que OP se refiere con respecto a las otras tablas.)¿ Todas esas tablas tienen una
1-to-1
relación? Por ejemplo, ¿cada fila de usuario solo tendrá una fila correspondiente enuser_stats
ouser_levels
? Si es así, podría tener sentido combinarlos en una sola tabla. Sin embargo, si la relación no es así1 to 1
, probablemente no tendría sentido combinarlos (desnormalizarlos).Tenerlos en tablas separadas frente a una tabla probablemente tendrá poco efecto en el rendimiento, a menos que tenga cientos de miles o millones de registros de usuarios. La única ganancia real que obtendrá es simplificar sus consultas combinándolas.
ETA:
Si lo que le preocupa es tener demasiadas columnas , piense qué cosas suele usar juntas y combínelas , dejando el resto en una tabla separada (o varias tablas separadas si es necesario).
Si observa la forma en que usa los datos, supongo que encontrará que aproximadamente el 80% de sus consultas usan el 20% de esos datos y el 80% restante de los datos se usa solo ocasionalmente. Combine ese 20% de uso frecuente en una tabla y deje el 80% que no usa con frecuencia en tablas separadas y probablemente tendrá un buen compromiso.
fuente
La creación de una tabla masiva va en contra de los principios de las bases de datos relacionales. No los combinaría todos en una sola tabla. Obtendrá varias instancias de datos repetidos. Si su usuario tiene tres intereses, por ejemplo, tendrá 3 filas, con los mismos datos de usuario solo para almacenar los tres intereses diferentes. Definitivamente opte por el enfoque de tablas múltiples 'normalizadas'. Vea esta página Wiki para la normalización de la base de datos.
Editar: He actualizado mi respuesta, ya que ha actualizado su pregunta ... Estoy de acuerdo con mi respuesta inicial incluso más ahora desde ...
Si, por ejemplo, un usuario no tenía ningún interés, si normaliza, entonces simplemente no tendrá una fila en la tabla de intereses para ese usuario. Si tiene todo en una tabla masiva, entonces tendrá columnas (y aparentemente muchas de ellas) que contienen solo NULL.
He trabajado para una empresa de telefonía donde ha habido toneladas de tablas, obtener datos podría requerir muchas uniones. Cuando el rendimiento de la lectura de estas tablas era crítico, se creaban procedimientos que podían generar una tabla plana (es decir, una tabla desnormalizada) que no requeriría uniones, cálculos, etc. a los que pudieran apuntar los informes. Estos se usaron luego junto con un agente de servidor SQL para ejecutar el trabajo en ciertos intervalos (es decir, una vista semanal de algunas estadísticas se ejecutaría una vez a la semana y así sucesivamente).
fuente
¿Por qué no utilizar el mismo enfoque que hace Wordpress al tener una tabla de usuarios con información básica de usuario que todos tienen y luego agregar una tabla "user_meta" que puede ser básicamente cualquier par clave, valor asociado con la identificación del usuario? Entonces, si necesita encontrar toda la metainformación del usuario, puede agregarla a su consulta. Tampoco siempre tendría que agregar la consulta adicional si no es necesaria para cosas como iniciar sesión. El beneficio de este enfoque también deja su mesa abierta para agregar nuevas funciones a sus usuarios, como almacenar su identificador de Twitter o cada interés individual. Tampoco tendrá que lidiar con un laberinto de ID asociados porque tiene una tabla que rige todos los metadatos y la limitará a una sola asociación en lugar de 50.
Wordpress hace esto específicamente para permitir que se agreguen funciones a través de complementos, lo que permite que su proyecto sea más escalable y no requerirá una revisión completa de la base de datos si necesita agregar una nueva función.
fuente
wp_usermeta
tabla de Wordpress crece geométricamente. Cada usuario agrega X filas a lawp_usermeta
tabla, una fila por cada pieza de metainformación que queremos mantener para ese usuario. Si mantiene 8 campos personalizados para cada usuario, eso significa que wp_usermeta tendráusers * 8
filas de largo. Esto parece estar causando problemas de rendimiento, pero no estoy seguro de si ese es el problema o no…get_users()
) solo para calcular la paginación. Una vez que corregimos el código para usar unaSELECT COUNT(…)
consulta para la paginación, el tiempo de carga de la página pasó de 28 segundos a aproximadamente 400 ms. Todavía me pregunto cómo se compara el rendimiento con las tablas unidas o una sola tabla plana ... He tenido problemas para encontrar métricas de rendimiento en la web.Creo que esta es una de esas situaciones de "depende". Tener varias tablas es más limpio y probablemente teóricamente mejor. Pero cuando tiene que unir 6-7 tablas para obtener información sobre un solo usuario, puede comenzar a repensar ese enfoque.
fuente
Yo diría que depende de lo que realmente signifiquen las otras tablas. ¿Un user_details contiene más de 1 usuario / más y así sucesivamente? El nivel de normalización que mejor se adapte a sus necesidades depende de sus demandas.
Si tiene una tabla con un buen índice, probablemente sea más rápido. Pero por otro lado probablemente sea más difícil de mantener.
Para mí, parece que podría omitir User_Details, ya que probablemente sea una relación 1 a 1 con los usuarios. ¿Pero el resto son probablemente muchas filas por usuario?
fuente