Digamos que eu tenha uma tabela grande que contém as informações do usuário e outra tabela que contém vários locais. Então eu uso outra tabela que contém o user_id e o location_id.
Para recuperar os dados, tenho que usar a consulta Left Join. Isso não torna todo o processo mais longo para recuperar em vez de ter tudo em uma tabela? Por exemplo, eu poderia ter a localização como texto na mesma tabela.
EDIT: Aqui está um exemplo.
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`name` varchar(45) DEFAULT NULL,
`gender` enum('M','F') DEFAULT NULL
);
CREATE TABLE `user_location` (
`user_id` int(11) NOT NULL,
`location_id` int(11) NOT NULL
);
CREATE TABLE `location` (
`id` int(11) NOT NULL,
`location` varchar(45),
`parent_id` varchar(45)
);
Observação: assuma que todos os campos relacionados estão indexados corretamente entre eles.
Editar: atualmente tenho um grande banco de dados com usuários que recuperam sua localização por meio de uma tabela de junção, conforme descrito acima. Me pediram para otimizar o banco de dados porque os resultados da pesquisa são lentos. Eu adicionei memcache
e melhorou significativamente, mas agora estou apenas querendo saber sobre Left Joins.
Por exemplo, A consulta atual é algo assim:
SELECT * FROM users
LEFT JOIN user_location
ON user_location.user_id = user.id
LEFT JOIN location
ON location.id = user_location.location_id;
E isso é apenas para obter a localização. Eles têm vários outros campos que são recuperados por meio de junções e todos são necessários para visualizar o perfil de um usuário. Temos números de telefone, endereços, senhas, DOB e muitos outros em tabelas diferentes.
Para que eu crie uma página para o perfil do usuário, tenho que enviar ao servidor uma consulta grande. Agora, após a primeira vez, ele é armazenado em cache e está tudo bem. Mas eu só estava me perguntando por que alguém construiria seu banco de dados assim?
Se você colocar tudo em uma tabela, terá uma tabela maior e redundante.
Se todas as tabelas estiverem indexadas corretamente, a solução de 3 tabelas será rápida, pois um pequeno número de linhas será lido para cada consulta.
As tabelas de junção são uma prática padrão no design de banco de dados relacional.
Se você tiver um relacionamento muitos-para-muitos entre duas entidades, a maneira padrão de representá-las é com três tabelas.
Duas das tabelas são tabelas de entidade, com uma chave primária. Uma tabela de junção fica entre eles (logicamente) e contém duas chaves estrangeiras, uma que faz referência a cada tabela de entidade. Muitas vezes, essas duas chaves estrangeiras serão as duas únicas colunas na tabela de junção.
"Por favor, assuma que todos os campos relacionados estão devidamente indexados entre eles." Não, eu não vou fazer isso. Vejo muitos usuários que nunca ouviram falar de índices "compostos", muito menos entendem sua importância.
Em particular, você deve ter:
Outras notas estão no meu blog .
Sua abordagem com DB está errada. Uma tabela não é um monte de campos para armazenar dados que você manipula adicionando/removendo colunas sem critérios. A estrutura do banco de dados é o resultado de uma análise. Esta parte do Db nasceu de requisitos específicos: Um usuário mora em um ou mais locais. No mesmo local pode morar um ou mais usuários. Um usuário é identificado por um nome e sexo. Um local é identificado por id. Com base nesses requisitos, você identifica 2 entidades: Usuários e locais. Como a associação entre essas entidades é muitos Para muitos, transformando o esquema conceitual para ER, você obterá (matematicamente) uma tabela específica referente a UsersLocations, composta (no mínimo) por duas chaves estrangeiras que apontam para ambas as entidades. Como o nome não pode ser usado como chave primária (porque Pessoas podem ter o mesmo nome), você usa um ID (provavelmente com um incremento automático).
Se você tiver um EAV , basta
INSERT
um valor padrão delocation_id =
0 ou 1 e sua descrição seria Undefined ou Not Set em sualocations
tabela. Faça um gatilho queINSERT
por padrão na tabela com ouser_id
elocation_id
.Assim, você não precisa usar
LEFT JOIN
e fazer a busca devagar, apenas um arquivoJOIN
. Se o usuário tiver olocation_id=
0 ou 1 (o que você tirou) vai retornar o padrãolocation_name
.A propósito, a
LEFT JOIN
sintaxe dependerá do seu índice. Se você tiver um índice nesses campos, não vejo o problema se suausers
tabela não for grande (assumindo).