AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 10199
Accepted
roxrook
roxrook
Asked: 2012-01-06 05:52:21 +0800 CST2012-01-06 05:52:21 +0800 CST 2012-01-06 05:52:21 +0800 CST

Como devo projetar uma tabela de relacionamento para amizade?

  • 772

Se Afor um amigo de B, devo armazenar os dois valores ABe BA, ou um é suficiente? Quais são as vantagens e desvantagens de ambos os métodos.

Segue minha observação:

  • Se eu mantiver os dois, terei que atualizar ambos quando receber uma solicitação de um amigo.
  • Se eu não mantiver os dois, achei difícil ter que fazer vários JOINcom essa tabela.

Atualmente, mantenho o relacionamento de um jeito.

insira a descrição da imagem aqui

Então o que devo fazer neste caso? Algum conselho?

mysql relational-theory
  • 5 5 respostas
  • 42688 Views

5 respostas

  • Voted
  1. Best Answer
    datagod
    2012-01-06T07:35:00+08:002012-01-06T07:35:00+08:00

    Eu armazenaria AB e BA. Uma amizade é realmente uma relação de mão dupla, cada entidade está ligada a outra. Embora intuitivamente pensemos na "amizade" como um elo entre duas pessoas, do ponto de vista relacional é mais como "A tem um amigo B" e "B tem um amigo A". Dois relacionamentos, dois registros.

    • 32
  2. Martin Smith
    2012-01-06T08:16:33+08:002012-01-06T08:16:33+08:00

    Se a amizade pretende ser simétrica (ou seja, não é possível A ser amigo, Bmas não vice-versa), então eu apenas armazenaria o relacionamento unidirecional com uma restrição de verificação, garantindo que cada relacionamento só possa ser representado de uma maneira.

    Além disso, eu abandonaria o id substituto e teria um PK composto (e possivelmente um índice exclusivo composto também nas colunas invertidas).

    CREATE TABLE Friends
      (
         UserID1 INT NOT NULL REFERENCES Users(UserID),
         UserID2 INT NOT NULL REFERENCES Users(UserID),
         CONSTRAINT CheckOneWay CHECK (UserID1 < UserID2),
         CONSTRAINT PK_Friends_UserID1_UserID2 PRIMARY KEY (UserID1, UserID2),
         CONSTRAINT UQ_Friends_UserID2_UserID1 UNIQUE (UserID2, UserID1)
      ) 
    

    Você não diz as consultas que isso dificulta, mas sempre pode criar uma View

    CREATE VIEW Foo
    AS
    SELECT UserID1,UserID2 
    FROM Friends
    UNION ALL
    SELECT UserID2,UserID1 
    FROM Friends
    
    • 14
  3. db2
    2012-01-06T10:00:40+08:002012-01-06T10:00:40+08:00

    Assumindo que uma "amizade" é sempre de mão dupla/mútua, eu provavelmente lidaria com algo assim.

    CREATE TABLE person (
        person_id int IDENTITY(1,1) PRIMARY KEY,
        ...other columns...
    )
    
    CREATE TABLE friendship (
        friendship_id int IDENTITY(1,1) PRIMARY KEY,
        ...other columns, if any...
    )
    
    CREATE TABLE person_friendship (
        person_id int NOT NULL,
        friendship_id int NOT NULL
        PRIMARY KEY (person_id, friendship_id)
    )
    

    O resultado é que você muda de uma junção muitos para muitos de "pessoa" para "pessoa", para uma junção muitos para muitos de "pessoa" para "amizade". Isso simplificará junções e restrições, mas tem o efeito colateral de permitir mais de duas pessoas em uma única "amizade" (embora talvez a flexibilidade adicional seja uma vantagem potencial).

    • 7
  4. RolandoMySQLDBA
    2012-01-06T11:50:25+08:002012-01-06T11:50:25+08:00

    Você pode precisar definir índices em torno de amizades em vez de dobrar o número de linhas:

    CREATE TABLE person
    (
        person_id INT NOT NULL AUTO_INCREMENT,
        ...
        PRIMARY KEY (person_id)
    );
    CREATE TABLE friendship
    (
        friend_of INT NOT NULL,
        friend_to INT NOT NULL,
        PRIMARY KEY (friend_of,friend_to),
        UNIQUE KEY friend_to (friend_to,friend_of)
    );
    

    Dessa forma, você dobra o armazenamento para índices, mas não para os dados da tabela. Como resultado, isso deve representar uma economia de 25% no espaço em disco. O MySQL Query Optimizer escolherá executar apenas varreduras de intervalo de índice, e é por isso que o conceito de cobertura de índices funciona bem aqui.

    Aqui estão alguns links interessantes sobre Índices de Cobertura:

    • http://peter-zaitsev.livejournal.com/6949.html
    • http://www.mysqlperformanceblog.com/2006/11/23/covering-index-and-prefix-indexes/
    • http://ronaldbradford.com/blog/tag/covering-index/

    EMBARGO

    Se a amizade não é mútua, você tem a base para outro tipo de relacionamento : SEGUIDOR

    Se friend_to não for amigo de friend_of, você pode simplesmente deixar esse relacionamento fora da mesa.

    Se você quiser definir relacionamentos para todos os tipos, sejam eles mútuos ou não, provavelmente poderá usar o seguinte layout de tabela:

    CREATE TABLE person
    (
        person_id INT NOT NULL AUTO_INCREMENT,
        ...
        PRIMARY KEY (person_id)
    );
    CREATE TABLE relationship
    (
        rel_id INT NOT NULL AUTO_INCREMENT,
        person_id1 INT NOT NULL,
        person_id2 INT NOT NULL,
        reltype_id TINYINT,
        PRIMARY KEY (rel_id),
        UNIQUE KEY outer_affinity (reltype_id,person_id1,person_id2),
        UNIQUE KEY inner_affinity (reltype_id,person_id2,person_id1),
        KEY has_relationship_to (person1_id,reltype_id),
        KEY has_relationship_by (person2_id,reltype_id)
    );
    CREATE TABLE relation
    (
        reltype_id TINYINT NOT NULL AUTO_INCREMENT,
        rel_name VARCHAR(20),
        PRIMARY KEY (reltype_id),
        UNIQUE KEY (rel_name)
    );
    INSERT INTO relation (relation_name) VALUES
    ('friend'),('follower'),('foe'),
    ('forgotabout'),('forsaken'),('fixed');
    

    Na tabela de relações, você pode organizar as relações para incluir o seguinte:

    • Os amigos devem ser mútuos
    • Os inimigos podem ser mútuos ou não
    • Os seguidores podem ser mútuos ou não
    • As outras relações estariam sujeitas a interpretação (pelo esquecido ou abandonado ou o destinatário da vingança (fixo))
    • Possíveis relacionamentos podem ser estendidos ainda mais

    Isso deve ser mais robusto para todos os relacionamentos, sejam eles mútuos ou não.

    • 5
  5. appartisan
    2015-12-10T04:54:39+08:002015-12-10T04:54:39+08:00

    Se você pode controlar dentro do aplicativo que o id de A é sempre menor que o id de B (pré-encomendar os ids dos elementos A,B) você pode aproveitar de pedir sem um OR (selecione onde id_A = a AND id_B = b, em vez de perguntar (id_A = a AND id_B = b) OR (id_A = b AND id_B = a) ), e também manter metade dos registros necessários com as outras aproximações. Em seguida, você deve usar outro campo para manter o estado do relacionamento ( are-friends, a-solicited-to-b, b-solicited-to-a, exfriends-a, exfriends-b ), e pronto.

    Esta é a maneira que eu gerenciei meu sistema de amizade, e isso simplifica o sistema e usa metade das linhas que você precisa com outros sistemas, apenas dizendo que A é igual ao valor de id mais baixo no código.

    • 1

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve