Cenário
Imagine que temos um table
usuário e um item
usuário. Essas 2 tabelas possuem uma tabela associativa chamada user_item
para definir um many to many
relacionamento.
Começamos 100
item
registrosTemos 500 milhões
user
de registros.Portanto devemos gerar 50_000_000_000
user_item
(50 bilhões)Poderíamos potencialmente ter ainda mais
Não será fácil fragmentar nem particionar porque isso tornará qualquer outra operação mais lenta (caso contrário, precisaremos verificar tudo)
Assuma como padrão de consulta (
INSERT
,SELECT
,UPDATE
) padrões m2m básicos/típicos (que podem ser encontrados em qualquer tutorial ou exemplo
Pergunta
Qual é o melhor design ou solução conhecida para lidar com bilhões de relacionamentos Muitos para Muitos em um banco de dados, independentemente de um esquema?
Esquema
Imagine este esquema simples
CREATE DATABASE IF NOT EXISTS `playground` CHARACTER SET = latin1;
USE playground;
CREATE TABLE IF NOT EXISTS `user`
(
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`),
INDEX `user__name_fk` (`name`)
) ENGINE = InnoDB
DEFAULT CHARSET = latin1
ROW_FORMAT = DYNAMIC;
CREATE TABLE IF NOT EXISTS `item`
(
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`),
INDEX `user__name` (`name`)
) ENGINE = InnoDB
DEFAULT CHARSET = latin1
ROW_FORMAT = DYNAMIC;
CREATE TABLE IF NOT EXISTS `user_item`
(
`user_id` BIGINT UNSIGNED NOT NULL,
`item_id` BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`, `item_id`),
INDEX `user_item__item` (`item_id`),
FOREIGN KEY `user_id_fk` (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE,
FOREIGN KEY `item_id_fk` (`item_id`) REFERENCES `item` (`id`) ON DELETE CASCADE
) ENGINE = InnoDB
DEFAULT CHARSET = latin1
ROW_FORMAT = DYNAMIC;
-- create some default items
INSERT INTO `item` (`name`) VALUES ('item_1'), ('item_2'), ('item_3'), ('item_4'), ('item_5'), ('item_6'), ('item_7'), ('item_8'), ('item_9'), ('item_10');
-- create some users
INSERT INTO `user` (`name`) VALUES ('user_1'), ('user_2'), ('user_3'), ('user_4'), ('user_5'), ('user_6'), ('user_7'), ('user_8'), ('user_9'), ('user_10');
INSERT INTO `user_item` (`user_id`, `item_id`) VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10);
Mais informações
Não estou perguntando como usar o relacionamento muitos para muitos no MySQL, eu sei disso. Estou perguntando qual é a solução mais conhecida para um problema de escala, ou seja, quando o número de registros relacionados está crescendo exponencialmente em uma escala tão grande.
Além disso, intencionalmente não adicionei nenhum padrão de consulta ( INSERT
, SELECT
, UPDATE
) porque é irrelevante . Suponha o padrão M2M mais típico. Não quero perder o foco na questão real que é sobre escalabilidade e enorme quantidade de dados.
Deve haver algum truque ou alguma solução alternativa conhecida, certo? Também estou considerando um banco de dados NoSQL, então a resposta pode incluir qualquer coisa não relacionada ao MySQL (ou qualquer banco de dados SQL),
Sinto que este deveria ser um problema comum que muitas grandes empresas enfrentarão e, portanto, deveria haver uma solução comum (ou poucas). A causa raiz desse problema é que, embora o MySQL seja ótimo para criar relacionamentos, ele aumentará exponencialmente a tabela associativa m2m .
Os 500 milhões x 100 == 50 bilhões são apenas um exemplo. Mas poderia teoricamente acontecer.
Esclarecimento
- Deixei a consulta de propósito porque você pode assumir a mais fácil.
- Tenho certeza que se eu der alguns exemplos, começarei a aparecer a otimização na consulta específica, essa não é a questão
- Estou fazendo uma pergunta de alto nível e, se não houver uma solução real conhecida, um não explicando o porquê seria suficiente (presumindo que esteja correto)
Aqui está um exemplo de uma consulta simples de muitos para muitos.
SELECT user.*, item.* FROM user
LEFT JOIN user_item ON user.id = user_item.user_id
LEFT JOIN item ON item.id = user_item.item_id
WHERE user.name = 'user_1';
Perguntas semelhantes, mas não iguais