2010-03-18 22 views
5

Estoy planeando construir algún proyecto de base de datos.Tabla con muchos atributos

Una de las tablas tiene muchos atributos.

Mi pregunta es: ¿qué es mejor, para dividir la clase en 2 tablas separadas o ponerlas todas en una sola tabla. a continuación es un ejemplo

create table User { id, name, surname,... show_name, show_photos, ...) 

o

create table User { id, name, surname,...) 
create table UserPrivacy {usr_id, show_name, show_photos, ...) 

El rendimiento supongo que es similar debido a i puedo usar índice.

+0

¿Qué quiere decir con "Mejor"? ¿Más rápido? Más barato? Más simple? Se usó más memoria? ¿Se utilizan más E/S? Mayor tasa de facturación? Más seguridad laboral? –

+0

Creo que el tiempo es aproximadamente el mismo, la memoria también, pero el uso de E/S: vale la pena considerar – Robert

Respuesta

-2

Sugeriría algo differnet. Parece probable que en el futuro se le preguntará por "otro atributo más" para administrar. En lugar de agregar una columna, puede agregar una fila a una tabla de atributos:

TABLE Attribute 
(
    ID 
    Name 
) 
TABLE User 
(
    ID 
    ... 
) 
TABLE UserAttributes 
(
    UserID FK Users.ID 
    Attribute FK Attributes.ID 
    Value... 
) 

Buenos comentarios de todos. Debería haber sido más claro en mi respuesta.

Hacemos esto bastante para manejar casos especiales en los que los clientes nos piden que les adaptemos nuestro sitio de alguna forma. Nunca "pivotamos" los NVP en columnas en una consulta, siempre estamos preguntando "¿Debería hacer esto aquí?" buscando un atributo específico enumerado para un cliente. Si está allí, eso es un "verdadero". Por lo tanto, en lugar de tener una gran cantidad de columnas booleanas, la mayoría de las cuales serían falsas o nulas para la mayoría de los clientes, Y la tendencia de que estas características crezcan en número, esto nos funciona bien.

+5

Esta es una sugerencia que no se escalará bien. Se sabe que las tablas EAV son extremadamente pobres y en la mayoría de los casos deben evitarse. – HLGEM

+1

Lucho contra los EAV como si fuera St. George, son un dragón. Pero N8 es correcto, si la ÚNICA consulta que desea ejecutar es como la suya, "¿Debo hacer esto para este usuario? Está bien. Es un acceso de índice único para una fila ... ¿Debería N8 alguna vez tratar de encontrar TODOS el cliente que tiene dos o más privilegios puede hacer la cena. –

0

Debería considerar dividir la tabla si todos los atributos de privacidad son nulos y probablemente tendrá valores de NULL.

Esto le ayudará a mantener la tabla principal más pequeña.

Si los atributos de privacidad se rellenarán en su mayoría, no tiene sentido dividir la tabla, ya que se necesitarán JOIN s adicionales para recuperar los datos.

2

Diría las 2 tablas separadas, especialmente si está utilizando ORM. En la mayoría de los casos, es mejor que cada tabla se corresponda con un objeto particular y que su campo o "atributos" sean elementos necesarios para describir ese objeto.

No necesita 'mostrar_fotos' para describir a un Usuario, pero sí lo necesita para describir UserPrivacy.

+0

show_photos y show_name son atributos del usuario. Con ORM, generalmente todos los atributos se cargarán ya sea que los use o no. Es posible que desee cargar el Usuario sin cargar su configuración de privacidad. Esa sería una razón para dividirlos. Aunque todavía agregaría el método a la clase de usuario como getUserPrivacy(). Sin embargo, está complicando las cosas para el rendimiento. –

+1

Puede tener todos los elementos en una tabla, pero use las vistas para evitar que el ORM 'vea' todas las columnas a la vez –

+1

Podría decir sí, pero ¿eso no contradice un poco? Asumiría que estarías usando ORM en primer lugar para organizarse, entre otras cosas. ¿Por qué no extiendes eso a tu base de datos? – KTastrophy

-2

Por qué no tienen una tabla de usuario y características de las tablas, por ejemplo:

create table User (id int primary key, name varchar(255) ...)

create table Features ( user_id int, feature varchar(50), enabled bit, primary key (user_id, feature) )

A continuación, los datos de la tabla de Características se vería así:

 
| user_id | feature  | enabled 
| ------------------------------- 
| 291  | show_photos | 1 
| ------------------------------- 
| 291  | show_name | 1 
| ------------------------------- 
| 292  | show_photos | 0 
| ------------------------------- 
| 293  | show_name | 0 
+1

Abajo votaron ya que estos no escalan bien –

+1

Por favor, no vaya en esta dirección. No escala, es imposible consultar bien, no se puede indexar, es una mala idea. Solo google EAV. Es un patrón de mal diseño tan común que tiene su propio nombre. –

+0

Este patrón de mal diseño es tan malo que tiene su propio nombre: EAV. Busca todas las historias de terror o busca otras publicaciones/comentarios sobre SO por mí. –

4

Es mejor poner todos los atributos en la misma mesa

Si comienza a almacenar nombres de atributos en una tabla, está almacenando metadatos en su base de datos, que rompe la primera forma normal.

Además, mantenerlos todos en la misma tabla simplifica sus consultas.

le gustaría tener:

SELECT show_photos FROM User WHERE user_id = 1 

O

SELECT up.show_photos FROM User u 
LEFT JOIN UserPrivacy up USING(user_id) 
WHERE u.user_id = 1 

combinaciones estén bien, pero mantenerlos para asociar entidades separadas y 1-> N relaciones.

Hay un límite en el número de columnas, y solo si crees que podrías alcanzar ese límite, harías cualquier otra cosa.

Existen razones legítimas para almacenar pares de nombre de nombre en una tabla separada, pero el temor de agregar columnas no es uno de ellos. Por ejemplo, crear una tabla de valores de nombre puede, en algunas circunstancias, facilitarle la consulta de una lista de atributos. Sin embargo, la mayoría de los motores de base de datos, incluido PDO en PHP, incluyen métodos de reflexión mediante los cuales puede obtener fácilmente una lista de columnas para una tabla (atributos para una entidad).

Además, tenga en cuenta que su campo de Id. En Usuario debe ser user_id, no solo id, a menos que esté usando Ruby, lo que obliga a la identificación. 'User_id' es preferido porque con sólo ID, su une a tener este aspecto:

ON u.id = up.user_id 

que parece extraño, y la forma preferida es la siguiente:

ON u.user_id = up.user_id 

o más simplemente:

USING(user_id) 

No tenga miedo de 'agregar otro atributo'. Es normal, y está bien.

+0

No voto abajo Marcus, pero no estoy de acuerdo. Agregar una columna a una tabla en un DB de producción es bastante importante. En cuanto a las identificaciones, bueno, eso se debatió un poco aquí en el 'desbordamiento;) – n8wrl

+1

@ n8wrl, gracias por la entrada. Depende del sistema si es un gran problema. Si el sistema está demasiado ocupado, puede esperar la próxima ventana de mantenimiento o las horas pico. Se prefiere tomar el golpe de una vez, que se escala mejor que el código adicional y el trabajo requerido para administrar el otro sistema. –

+2

n8wrl, agregar una columna a una tabla prod grande es FAR preferible a usar una tabla EAV. Las tablas EAV son más laboriosas de mantener (por ejemplo, no tengo ni idea de cómo se unirá a las cosas que tendré que hacer para obtener los datos) y consultar y son asesinos de rendimiento. – HLGEM

0

Dado que esta parece ser una relación uno a uno, yo normalmente mantener todo en una mesa a menos:

Usted sería cerca del límite de la cantidad de bytes que se pueden almacenar en una fila - a continuación, deberías dividirlo

O si normalmente consultará la tabla principal por separado y no necesitará esos campos la mayor parte del tiempo.

0

Si algunas columnas es (no identifiable or dependent en el primary key) o (los valores de un conjunto definite/fixed se está utilizando repeatedly) de la Tabla hacer una tabla diferente para esas columnas y mantener una relación uno a uno.

Cuestiones relacionadas