Veja o desempenho no MySQL para desnormalização
-
20-09-2019 - |
Pergunta
Atualmente, estou escrevendo meu primeiro aplicativo PHP verdadeiramente e gostaria de saber como projetar/projetar/implementar as visualizações MySQL corretamente;
No meu caso, os dados do usuário de caso estão espalhados por várias tabelas (como conseqüência da normalização do banco de dados) e eu estava pensando em usar uma visão para agrupar dados em uma tabela grande:
CREATE VIEW `Users_Merged` (
name,
surname,
email,
phone,
role
) AS (
SELECT name, surname, email, phone, 'Customer'
FROM `Customer`
)
UNION (
SELECT name, surname, email, tel, 'Admin'
FROM `Administrator`
)
UNION (
SELECT name, surname, email, tel, 'Manager'
FROM `manager`
);
Dessa forma, posso usar os dados da visualização do aplicativo PHP facilmente, mas realmente não sei quanto isso pode afetar o desempenho.
Por exemplo:
SELECT * from `Users_Merged` WHERE role = 'Admin';
É a maneira certa de filtrar os dados da View ou devo filtrar antes de criar a própria visualização? (Preciso que isso tenha uma lista de usuários e a funcionalidade para filtrá -los por função).
EDITAR
Especificamente, o que estou tentando obter é desnormalização de três tabelas em uma. Minha solução está correta?Veja desnormalização na Wikipedia
Solução
Em geral, o mecanismo de banco de dados executará a otimização para você. Isso significa que o mecanismo descobrirá que a tabela de usuários precisa ser filtrada antes de ser unida às outras tabelas.
Então, vá em frente e use sua visualização e deixe o banco de dados se preocupar com isso.
Se você detectar um desempenho ruim mais tarde, use o MySQL, explique para obter o MySQL para dizer o que está fazendo.
PS: Seu design de dados permite apenas uma função por usuário, é isso que você queria? Nesse caso, e se a consulta de exemplo que você deu é uma que você pretende executar com frequência, indexe a coluna de função nos usuários.
Outras dicas
Se você tem <1000 usuários (o que parece provável), não importa como você faz isso. Se é improvável que a lista de usuários mude por longos períodos de tempo, o melhor que você provavelmente pode fazer em termos de desempenho é carregar a lista de usuários na memória e não ir ao banco de dados. Mesmo que os dados do usuário mudassem enquanto isso, você poderia atualizar a estrutura da memória e o banco de dados e, novamente, não precisar ler as informações do usuário do banco de dados.
Você provavelmente estaria muito melhor normalizando os administradores, usuários, gerentes e o que você fez em uma mesa uniforme com uma coluna discriminadora "função" que economizaria muita duplicação, que é essencialmente a razão para fazer a normalização no primeiro Lugar, colocar. Você pode adicionar os detalhes específicos da função a tabelas distintas que você usa com a tabela de usuários em uma junção.
Sua consulta pode parecer tão simples quanto:
SELECT
`Name`, `Surname`, `Email`, `Phone`, `Role`
FROM `User`
WHERE
`User`.`Role` IN('Administrator','Manager','Customer', ...)
O que também é mais fácil para o banco de dados processar do que um conjunto de union
s
Se você der um passo adiante, poderá adicionar um UserRoleCoupling
Tabela (em vez do Role
coluna in User
) que possui todas as funções que um usuário possui por usuário:
CREATE TABLE `UserRoleCoupling` (
UserID INT NOT NULL, -- assuming your User table has and ID column of INT
RoleID INT NOT NULL,
PRIMARY KEY(UserID, RoleID)
);
E coloque as informações reais de função em uma tabela separada também:
CREATE TABLE `Role` (
ID INT NOT NULL UNIQUE AUTO_INCREMENT,
Name VARCHAR(64) NOT NULL
PRIMARY KEY (Name)
)
Agora você pode ter várias funções por usuário e usar consultas como
SELECT
`U`.`Name`
,`U`.`Surname`
,`U`.`Email`
,`U`.`Phone`
,GROUP_CONCAT(`R`.`Name`) `Roles`
FROM `User`
INNER JOIN `UserGroupCoupling` `UGC` ON `UGC`.`UserID` = `User`.`ID`
INNER JOIN `Role` `R` ON `R`.`ID` = `UGC`.`RoleID`
GROUP BY
`U`.`Name`, `U`.`Surname`, `U`.`Email`, `U`.`Phone`
O que te daria o básico User
detalhes e uma lista separada de vírgula de todos os atribuídos Role
nomes.
Em geral, a melhor maneira de normalizar uma estrutura de banco de dados é tornar as tabelas o mais genéricas possível sem ser redundante; portanto, não adicione detalhes do administrador ou do cliente à tabela de usuários, mas use um relacionamento entre User
e Administrator
Para encontrar os detalhes específicos do administrador. A maneira como você está fazendo isso agora não é realmente normalizada.
Vou ver se consigo encontrar meu livro favorito sobre a normalização do banco de dados e postar o ISBN quando tiver tempo mais tarde.