Sou desenvolvedor de software. Adoro codificar, mas odeio bancos de dados ... Atualmente, estou criando um site no qual um usuário poderá marcar uma entidade como curtida (como no FB), marcá- la e comentar .
Fico preso no design de tabelas de banco de dados para lidar com essa funcionalidade. A solução é trivial, se pudermos fazer isso apenas para um tipo de coisa (por exemplo, fotos). Mas preciso habilitar isso para cinco coisas diferentes (por enquanto, mas também presumo que esse número possa crescer à medida que o serviço inteiro cresce).
Encontrei algumas perguntas semelhantes aqui, mas nenhuma delas tem uma resposta satisfatória, por isso estou fazendo essa pergunta novamente.
A questão é: como projetar o banco de dados de maneira adequada, eficiente e elástica , para que ele possa armazenar comentários para tabelas diferentes , curtidas para tabelas e tags diferentes para elas. Algum padrão de design como resposta será melhor;)
Descrição detalhada : Eu tenho uma tabela User
com alguns dados do usuário e mais 3 tabelas : Photo
com fotografias , Articles
com artigos , Places
com lugares . Quero habilitar qualquer usuário logado para:
comentar em qualquer uma dessas 3 tabelas
marque qualquer um deles como desejado
marcar qualquer um deles com alguma tag
Também quero contar o número de curtidas para cada elemento e o número de vezes que essa tag específica foi usada.
1 r abordagem :
a) Para as tags , vou criar uma tabela Tag [TagId, tagName, tagCounter]
, então eu vou criar muitos-para-muitos relacionamentos mesas para: Photo_has_tags
, Place_has_tag
, Article_has_tag
.
b) O mesmo vale para comentários.
c) I irá criar uma tabela LikedPhotos [idUser, idPhoto]
, LikedArticles[idUser, idArticle]
, LikedPlace [idUser, idPlace]
. O número de curtidas será calculado por consultas (que, suponho, são ruins). E...
Eu realmente não gosto deste design para a última parte, ele cheira muito mal para mim;)
2 nd abordagem :
Vou criar uma tabela ElementType [idType, TypeName == some table name]
que será preenchida pelo administrador (eu) com os nomes das tabelas que podem ser curtidas , comentadas ou marcadas . Então eu vou criar tabelas :
a) LikedElement [idLike, idUser, idElementType, idLikedElement]
e o mesmo para Comentários e Tags com as colunas apropriadas para cada um. Agora, quando eu quiser fazer uma foto curtida, inserirei:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)
e para lugares:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)
e assim por diante ... Acho que a segunda abordagem é melhor, mas também sinto que algo está faltando nesse design ...
Por fim, também me pergunto qual é o melhor local para armazenar o contador quantas vezes o elemento foi curtido. Só consigo pensar em duas maneiras:
- na
Photo/Article/Place
tabela element ( ) - por contar count ().
Espero que minha explicação sobre o assunto seja mais completa agora.
Respostas:
A solução mais extensível é ter apenas uma tabela "base" (conectada a "curtidas", tags e comentários) e "herdar" todas as outras tabelas dela. Adicionar um novo tipo de entidade envolve apenas adicionar uma nova tabela "herdada" - ela se conecta automaticamente a toda a maquinaria como / tag / comment.
O termo de relacionamento da entidade para isso é "categoria" (consulte o Guia de Métodos do ERwin , seção: "Relacionamentos de subtipos"). O símbolo da categoria é:
Supondo que um usuário possa gostar de várias entidades, uma mesma tag pode ser usada para mais de uma entidade, mas um comentário é específico da entidade, e seu modelo pode ficar assim:
BTW, existem aproximadamente três maneiras de implementar a "categoria ER":
A menos que você tenha requisitos de desempenho muito rigorosos, a terceira abordagem é provavelmente a melhor (o que significa que as tabelas físicas correspondem 1: 1 às entidades no diagrama acima).
fonte
BIGINT
é 9223372036854775807. Supondo que você insira uma linha por segundo, os valores disponíveis acabarão em ~ 300 bilhões de anos. Certamente, você poderá portar números inteiros de 128 bits até lá!Como você "odeia" bancos de dados, por que você está tentando implementar um? Em vez disso, solicite ajuda de alguém que ama e respira essas coisas.
Caso contrário, aprenda a amar seu banco de dados. Um banco de dados bem projetado simplifica a programação, projeta o site e facilita sua operação contínua. Mesmo um designer de d / b experiente não terá uma previsão completa e perfeita: algumas mudanças de esquema no futuro serão necessárias conforme os padrões de uso surgirem ou os requisitos mudarem.
Se este for um projeto individual, programe a interface do banco de dados em operações simples usando procedimentos armazenados: add_user, update_user, add_comment, add_like, upload_photo, list_comments, etc. Não incorpore o esquema em nem uma linha de código. Dessa maneira, o esquema do banco de dados pode ser alterado sem afetar nenhum código: apenas os procedimentos armazenados devem saber sobre o esquema.
Pode ser necessário refatorar o esquema várias vezes. Isto é normal. Não se preocupe em aperfeiçoá-lo pela primeira vez. Basta torná-lo funcional o suficiente para criar um protótipo de um design inicial. Se você tiver o luxo do tempo, use-o um pouco e exclua o esquema e faça-o novamente. É sempre melhor na segunda vez.
fonte
Esta é uma idéia geral, por favor, não preste muita atenção ao estilo dos nomes dos campos, mas mais à relação e estrutura
Este pseudocódigo obterá todos os comentários da foto com o ID 5
SELECT * FROM ações
WHERE actions.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"
Esse pseudocódigo obterá todos os gostos ou usuários que curtiram a foto com o ID 5
(você pode usar count () para obter apenas o número de curtidas)
fonte
SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
id_stuff
coluna conterá valores exclusivos em cada uma das três tabelas?Tanto quanto eu entendo. várias tabelas são necessárias. Existe uma relação de muitos para muitos entre eles.
fonte
Veja os padrões de acesso necessários. Algum deles parece tornar particularmente difícil ou ineficiente minha escolha de um projeto ou outro?
Se não favorecer o que requer menos tabelas
Nesse caso:
Eu acho que sua abordagem "discriminada", opção 2, gera consultas mais simples em alguns casos e não parece muito pior nos outros, então eu continuaria.
fonte
Definitivamente, vá com a segunda abordagem, na qual você tem uma tabela e armazena o tipo de elemento para cada linha, ela oferece muito mais flexibilidade. Basicamente, quando algo pode ser feito logicamente com menos tabelas, é quase sempre melhor usar menos tabelas. Uma vantagem que me vem à mente agora sobre o seu caso específico, considere que você deseja excluir todos os elementos desejados de um determinado usuário. Com a sua primeira abordagem, é necessário emitir uma consulta para cada tipo de elemento, mas com a segunda abordagem, isso pode ser feito com apenas uma consulta ou considere quando você deseja adicionar um novo tipo de elemento, com a primeira abordagem envolve a criação de uma nova tabela para cada novo tipo, mas com a segunda abordagem, você não deve fazer nada ...
fonte
Considere usar tabela por entidade para comentários e etc. Mais tabelas - melhor sharding e dimensionamento. Não é um problema controlar muitas tabelas semelhantes para todas as estruturas que conheço.
Um dia, você precisará otimizar as leituras dessa estrutura. Você pode criar facilmente tabelas de agregação sobre as de base e perder um pouco nas gravações.
Uma grande mesa com dicionário pode se tornar incontrolável um dia.
fonte