Diseño de una estructura de base de datos de amistades: ¿Debería usar una columna de valores múltiples?

9

Digamos que tengo una tabla llamada User_FriendList, que tiene las siguientes características:

CREATE TABLE User_FriendList (
    ID ...,
    User_ID...,
    FriendList_IDs...,
    CONSTRAINT User_Friendlist_PK PRIMARY KEY (ID)
);

Y supongamos que dicha tabla contiene los siguientes datos:

 + ---- + --------- + --------------------------- +
 El | ID | ID_usuario | ID de lista de amigos             |
 + ---- + --------- + --------------------------- +
 El | 1 | 102 | 2: 15: 66: 35: 26: 17: |
 + ---- + --------- + --------------------------- +
 El | 2 | 114 1: 12: 63: 33: 24: 16: 102 |
 + ---- + --------- + --------------------------- +
 El | 3 | 117 6: 24: 52: 61: 23: 90: 97: 118 |
 + ---- + --------- + --------------------------- +

Nota: El ":" (dos puntos) es el delimitador cuando explota en PHP en un array.

Preguntas

Entonces:

  • ¿Es esta una forma conveniente de "almacenar" el IDsde un FriendList?

  • O, en cambio, ¿debería tener filas individuales con un solo FriendIdvalor en cada una de ellas y, cuando necesito recuperar todas las filas de una lista dada , simplemente realizar una consulta como SELECT * FROM UserFriendList WHERE UserId = 1?

gritar
fuente
3
Le recomiendo que lea esto: stackoverflow.com/questions/3653462/…
tombom
Es una forma algo conveniente de almacenar las ID, siempre y cuando no esté planeando hacer nada con ellas y no le importe especialmente la calidad de los datos.
mustaccio
Creo que codedodle.com/2014/12/social-network-friends-database.html podría ser una de las mejores soluciones.
Gupta

Respuestas:

19

Administrar una información individual

Suponiendo que, en su dominio comercial,

  • un usuario puede tener cero, uno o muchos amigos ;
  • un amigo primero debe estar registrado como usuario ; y
  • buscará, y / o agregará, y / o eliminará, y / o modificará valores únicos de una Lista de amigos ;

entonces cada dato específico reunido en la Friendlist_IDscolumna de valores múltiples representa una información separada que tiene un significado muy exacto. Por lo tanto, dicha columna

  • implica un grupo apropiado de restricciones explícitas, y
  • Sus valores tienen el potencial de ser manipulados individualmente por medio de varias operaciones relacionales (o combinaciones de las mismas).

Respuesta corta

En consecuencia, debe conservar cada uno de los Friendlist_IDsvalores en (a) una columna que acepte exclusivamente un único valor por fila en (b) una tabla que represente el tipo de asociación de nivel conceptual que puede tener lugar entre los Usuarios , es decir, una Amistad, como Ejemplificaré en las siguientes secciones:.

De esta manera, podrá manejar (i) dicha tabla como una relación matemática y (ii) dicha columna como un atributo de relación matemática , tanto como MySQL y su dialecto SQL lo permiten, por supuesto.

¿Por qué?

Debido a que el modelo relacional de datos , creado por el Dr. E. F. Codd , exige tener tablas compuestas de columnas que contengan exactamente un valor del dominio o tipo aplicable por fila; por lo tanto, declarar una tabla con una columna que puede contener más de un valor del dominio o tipo en cuestión (1) no representa una relación matemática y (2) no permitiría obtener las ventajas propuestas en el marco teórico mencionado anteriormente.

Modelado de amistades entre usuarios : primero se definen las reglas del entorno empresarial

Recomiendo comenzar a dar forma a una base de datos que delimite, antes que nada, el esquema conceptual correspondiente en virtud de la definición de las reglas comerciales relevantes que, entre otros factores, deben describir los tipos de interrelaciones que existen entre los distintos aspectos de interés, es decir , los tipos de entidad aplicables y sus propiedades ; p.ej:

  • Un usuario se identifica principalmente por su ID de usuario
  • Un usuario se identifica alternativamente por la combinación de su nombre , apellido , sexo y fecha de nacimiento.
  • Un usuario se identifica alternativamente por su nombre de usuario
  • Un usuario es el solicitante de cero o una o muchas amistades
  • Un usuario es el destinatario de cero o una o muchas amistades
  • Una amistad se identifica principalmente por la combinación de su RequesterId y su AddresseeId

Diagrama IDEF1X expositivo

De esta manera, pude derivar el diagrama IDEF1X 1 que se muestra en la Figura 1 , que integra la mayoría de las reglas formuladas anteriormente:

Figura 1. Diagrama IDEF1X de Amistades del Usuario

Como se muestra, Solicitante y Destinatario son denotaciones que expresan los Roles realizados por los Usuarios específicos que participan en una Amistad determinada .

Siendo así, el tipo de entidad Amistad retrata un tipo de asociación de relación de cardinalidad de muchos a muchos (M: N) que puede implicar diferentes ocurrencias del mismo tipo de entidad, es decir, Usuario . Como tal, es un ejemplo de la construcción clásica conocida como "Lista de materiales" o "Explosión de piezas".


1 La definición de integración para el modelado de información ( IDEF1X ) es una técnica altamente recomendable que fue establecida como estándar en diciembre de 1993 por el Instituto Nacional de Estándares y Tecnología (NIST) deEE. UU. Se basa sólidamente en (a) el material teórico inicial escrito por el único autor del modelo relacional, es decir, el Dr. EF Codd ; en (b) lavista de datos entidad-relación , desarrollada por el Dr. PP Chen ; y también en (c) la Técnica de diseño de base de datos lógica, creada por Robert G. Brown.


Diseño lógico ilustrativo de SQL-DDL

Luego, a partir del diagrama IDEF1X presentado anteriormente, declarar una disposición DDL como la que sigue es mucho más "natural":

-- You should determine which are the most fitting 
-- data types and sizes for all the table columns 
-- depending on your business context characteristics.

-- At the physical level, you should make accurate tests 
-- to define the mostconvenient INDEX strategies based on 
-- the pertinent query tendencies.

-- As one would expect, you are free to make use of 
-- your preferred (or required) naming conventions. 

CREATE TABLE UserProfile ( -- Represents an independent entity type.
    UserId          INT      NOT NULL,
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    BirthDate       DATE     NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    Username        CHAR(20) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT UserProfile_PK  PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- Single-column ALTERNATE KEY.
);

CREATE TABLE Friendship ( -- Stands for an associative entity type.
    RequesterId     INT      NOT NULL,
    AddresseeId     INT      NOT NULL, -- Fixed with a well-delimited data type.
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Friendship_PK            PRIMARY KEY (RequesterId, AddresseeId), -- Composite PRIMARY KEY.
    CONSTRAINT FriendshipToRequester_FK FOREIGN KEY (RequesterId)
        REFERENCES UserProfile (UserId),
    CONSTRAINT FriendshipToAddressee_FK FOREIGN KEY (AddresseeId)
        REFERENCES UserProfile (UserId)
);

De esta manera:

  • cada tabla base representa un tipo de entidad individual;
  • cada columna representa una propiedad exclusiva del tipo de entidad respectivo ;
  • un específicos tipo de datos una se fija para cada columna con el fin de garantizar que toda la valores que contiene pertenecen a un particular y bien definido conjunto , sea INT, DATETIME, CHAR, etc .; y
  • se configuran múltiples restricciones b (declarativamente) para garantizar que las aserciones en forma de filas retenidas en todas las tablas cumplan con las reglas de negocio determinadas en el esquema conceptual.

Ventajas de una columna de un solo valor

Como se demostró, puede, por ejemplo:

  • Aproveche la integridad referencial impuesta por el sistema de administración de bases de datos (DBMS por brevedad) para la Friendship.AddresseeIdcolumna, ya que restringirla como una CLAVE EXTRANJERA (FK por brevedad) que hace referencia a la UserProfile.UserIdcolumna garantiza que cada valor apunta a una fila existente .

  • Cree una CLAVE PRIMARIA compuesta (PK) compuesta por la combinación de columnas (Friendship.RequesterId, Friendship.AddresseeId), que ayude a distinguir con elegancia todas las filas INSERTADAS y, naturalmente, a proteger su singularidad .

    Por supuesto, esto significa que la conexión de una columna adicional para los valores sustitutos asignados por el sistema (por ejemplo, uno configurado con la propiedad IDENTITY en Microsoft SQL Server o con el atributo AUTO_INCREMENT en MySQL) y el INDEX auxiliar es completamente superfluo .

  • Restrinja los valores retenidos Friendship.AddresseeIda un tipo de datos preciso c (que debe coincidir, por ejemplo, con el establecido para UserProfile.UserId, en este caso INT), permitiendo que el DBMS se encargue de la validación automática pertinente .

    Este factor también puede ayudar a (a) utilizar las funciones de tipo incorporadas correspondientes y (b) optimizar el uso del espacio en disco .

  • Optimice la recuperación de datos a nivel físico configurando ÍNDICES subordinados pequeños y rápidos para la Friendship.AddresseeIdcolumna, ya que estos elementos físicos pueden ayudar sustancialmente a acelerar las consultas que involucran a dicha columna.

    Ciertamente, puede, por ejemplo, poner un ÍNDICE de una sola columna Friendship.AddresseeIdsolo, uno de varias columnas que abarque Friendship.RequesterIdy Friendship.AddresseeId, o ambos.

  • Evite la complejidad innecesaria introducida al "buscar" valores distintos que se recopilan juntos dentro de la misma columna (muy probablemente duplicados, mal escritos, etc.), un curso de acción que eventualmente ralentizaría el funcionamiento de su sistema, porque tiene que recurrir a métodos no relacionales que consumen recursos y tiempo para llevar a cabo dicha tarea.

Por lo tanto, existen múltiples razones que requieren analizar cuidadosamente el entorno empresarial relevante para marcar con precisión el tipo d de cada columna de la tabla.

Según lo expuesto, el papel desempeñado por el diseñador de la base de datos es primordial para hacer el mejor uso de (1) los beneficios de nivel lógico ofrecidos por el modelo relacional y (2) los mecanismos físicos proporcionados por el DBMS de elección.


a , b , c , d Evidentemente, cuando se trabaja con plataformas SQL (por ejemplo, Firebird y PostgreSQL ) que admiten la creación de DOMAIN (una característica relacional distintiva), puede declarar columnas que solo aceptan valores que pertenecen a sus respectivas (adecuadamente restringidas y, a veces, limitadas). compartido) DOMINIOS.


Uno o más programas de aplicación que comparten la base de datos bajo consideración

Cuando tiene que utilizar arraysel código de los programas de aplicación que acceden a la base de datos, simplemente necesita recuperar los conjuntos de datos relevantes en su totalidad y luego "vincularlos" a la estructura del código correspondiente o ejecutar el proceso (s) de aplicación (es) asociada (s) que deberían tener lugar.

Beneficios adicionales de las columnas de un solo valor: las extensiones de la estructura de la base de datos son mucho más fáciles

Otra ventaja de mantener el AddresseeIdpunto de datos en su columna reservada y debidamente tipada es que facilita considerablemente extender la estructura de la base de datos, como ejemplificaré a continuación.

Progresión del escenario: incorporación del concepto de estado de amistad

Dado que las amistades pueden evolucionar con el tiempo, es posible que deba realizar un seguimiento de dicho fenómeno, por lo que deberá (i) expandir el esquema conceptual y (ii) declarar algunas tablas más en el diseño lógico. Entonces, organicemos las siguientes reglas comerciales para delinear las nuevas incorporaciones:

  • Una amistad tiene uno a muchos estados de amistad
  • Un Estado de Amistad se identifica principalmente por la combinación de su RequesterId , su AddresseeId y su SpecifiedDateTime
  • Un usuario especifica cero-uno o muchos estados de amistad
  • Un estado clasifica cero-uno-o-muchos estados de amistad
  • Un estado se identifica principalmente por su código de estado
  • Un estado se identifica alternativamente por su nombre

Diagrama IDEF1X extendido

Sucesivamente, el diagrama IDEF1X anterior puede ampliarse para incluir los nuevos tipos de entidad y los tipos de interrelación descritos anteriormente. En la Figura 2 se presenta un diagrama que representa los elementos anteriores asociados con los nuevos :

Figura 2. Diagrama IDEF1X del estado de amistad

Adiciones de estructura lógica

Luego, podemos alargar el diseño DDL con las siguientes declaraciones:

--
CREATE TABLE MyStatus ( -- Denotes an independent entity type.
    StatusCode CHAR(1)  NOT NULL,
    Name       CHAR(30) NOT NULL,
    --
    CONSTRAINT MyStatus_PK PRIMARY KEY (StatusCode),
    CONSTRAINT MyStatus_AK UNIQUE      (Name) -- ALTERNATE KEY.
); 

CREATE TABLE FriendshipStatus ( -- Represents an associative entity type.
    RequesterId       INT      NOT NULL,
    AddresseeId       INT      NOT NULL,
    SpecifiedDateTime DATETIME NOT NULL,
    StatusCode        CHAR(1)  NOT NULL,
    SpecifierId       INT      NOT NULL,
    --
    CONSTRAINT FriendshipStatus_PK             PRIMARY KEY (RequesterId, AddresseeId, SpecifiedDateTime), -- Composite PRIMARY KEY.
    CONSTRAINT FriendshipStatusToFriendship_FK FOREIGN KEY (RequesterId, AddresseeId)
        REFERENCES Friendship  (RequesterId, AddresseeId), -- Composite FOREIGN KEY.
    CONSTRAINT FriendshipStatusToMyStatus_FK   FOREIGN KEY (StatusCode)
        REFERENCES MyStatus    (StatusCode),
    CONSTRAINT FriendshipStatusToSpecifier_FK  FOREIGN KEY (SpecifierId)
        REFERENCES UserProfile (UserId)      
);

En consecuencia, cada vez que el estado de una amistad determinada debe actualizarse, los usuarios solo tendrían que INSERTAR una nueva FriendshipStatusfila que contenga:

  • los valores adecuados RequesterIdy AddresseeIdtomados de la Friendshipfila correspondiente;

  • el StatusCodevalor nuevo y significativo extraído de MyStatus.StatusCode;

  • el instante exacto de INSERTion, es decir, SpecifiedDateTimepreferiblemente utilizando una función de servidor para que pueda recuperarlo y retenerlo de manera confiable; y

  • el SpecifierIdvalor que indicaría el respectivo UserIdque ingresó lo nuevo FriendshipStatusen el sistema, idealmente, con la ayuda de sus aplicaciones.

En ese sentido, supongamos que la MyStatustabla incluye los siguientes datos, con valores PK que son (a) amigables para el usuario final, programador de aplicaciones y DBA y (b) pequeños y rápidos en términos de bytes en el nivel de implementación física -:

 + -——————————- + -—————————- +
 El | StatusCode | Nombre       |
 + -——————————- + -—————————- +
 El | R | Solicitado |
 + ------------ + ----------- +
 El | A | Aceptado |
 + ------------ + ----------- +
 El | D | Rechazado |
 + ------------ + ----------- +
 El | B | Bloqued |
 + ------------ + ----------- +

Entonces, la FriendshipStatustabla puede contener datos como se muestra a continuación:

 + -———————————- + -———————————- + -———————————————————— ———- + -——————————- + -———————————- +
 El | RequesterId | AddresseeId | SpecifiedDateTime        | StatusCode | SpecifierId |
 + -———————————- + -———————————- + -———————————————————— ———- + -——————————- + -———————————- +
 El | 1750 | 1748 2016-04-01 16: 58: 12.000 | R | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 El | 1750 | 1748 2016-04-02 09: 12: 05.000 | A | 1748
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 El | 1750 | 1748 2016-04-04 10: 57: 01.000 | B | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 El | 1750 | 1748 2016-04-07 07: 33: 08.000 | R | 1748
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 El | 1750 | 1748 2016-04-08 12: 12: 09.000 | A | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +

Como puede ver, se puede decir que la FriendshipStatustabla tiene el propósito de comprender una serie de tiempo .


Publicaciones relevantes

Usted también podría estar interesado en:

  • En esta respuesta , sugiero un método básico para tratar una relación común de muchos a muchos entre dos tipos de entidades diferentes.
  • El diagrama IDEF1X que se muestra en la Figura 1 que ilustra esta otra respuesta . Preste especial atención a los tipos de entidad llamados Matrimonio y Progenie , porque son dos ejemplos más de cómo manejar el "Problema de explosión de piezas".
  • Esta publicación que presenta una breve deliberación sobre la celebración de diferentes piezas de información dentro de una sola columna.
MDCCL
fuente