Производительность просмотров в MySQL для денормализации - PullRequest
4 голосов
/ 15 марта 2010

В настоящее время я пишу свое действительно первое PHP-приложение, и я хотел бы знать, как правильно проектировать / проектировать / реализовывать MySQL Views;

В моем конкретном случае пользовательские данные распределены по нескольким таблицам (как следствие нормализации базы данных), и я подумывал использовать представление для группировки данных в одну большую таблицу:

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`
);

Таким образом, я могу легко использовать данные View из приложения PHP, но я не знаю, насколько это может повлиять на производительность.

Например:

SELECT * from `Users_Merged` WHERE role = 'Admin';

Правильный ли способ фильтрации данных представления или я должен фильтровать ДО создания самого представления? (Мне нужно, чтобы у меня был список пользователей и функции для фильтрации их по ролям).

EDIT

В частности, я пытаюсь получить денормализацию трех таблиц в одну. Правильно ли мое решение? См. Денормализация в Википедии

Ответы [ 3 ]

3 голосов
/ 15 марта 2010

Как правило, ядро ​​базы данных выполнит оптимизацию за вас. Это означает, что движок выяснит, что таблица пользователей должна быть отфильтрована перед присоединением к другим таблицам.

Итак, используйте ваше представление и позвольте базе данных беспокоиться об этом.

Если позже вы обнаружите низкую производительность, используйте MySQL EXPLAIN, чтобы MySQL сообщал вам, что он делает.

PS: Ваш дизайн данных предусматривает только одну роль для пользователя, это то, что вы хотели? Если это так, и если пример запроса, который вы задали, является тем, который вы собираетесь часто выполнять, убедитесь, что индексировал столбец роли в пользователях.

1 голос
/ 15 марта 2010

Если у вас <1000 пользователей (что кажется вероятным), то не имеет значения, как вы это делаете. Если список пользователей вряд ли изменится в течение длительных периодов времени, лучшее, что вы можете сделать с точки зрения производительности, - это загрузить список пользователей в память и вообще не переходить в базу данных. Даже если пользовательские данные тем временем изменятся, вы можете обновить структуру в памяти, а также базу данных, и, опять же, вам не придется считывать пользовательскую информацию из БД. </p>

0 голосов
/ 15 марта 2010

Вам, вероятно, было бы намного лучше нормализовать администраторов, пользователей, менеджеров и все, что у вас есть в одну унифицированную таблицу со столбцом дискриминатора «Роль», что позволило бы сэкономить большое количество дубликатов, что по сути является причиной для нормализации на первом месте. Затем можно добавить подробные сведения о роли в отдельные таблицы, которые вы используете с таблицей User в объединении.

Ваш запрос может выглядеть так просто:

SELECT
   `Name`, `Surname`, `Email`, `Phone`, `Role`
FROM `User`
WHERE 
    `User`.`Role` IN('Administrator','Manager','Customer', ...)

Что также проще для базы данных обрабатывать, чем набор union s

Если вы сделаете еще один шаг, вы можете добавить таблицу UserRoleCoupling (вместо столбца Role в User), которая содержит все роли, которые пользователь имеет для пользователя:

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)
);

И поместите фактическую информацию о роли в отдельную таблицу:

CREATE TABLE `Role` (
    ID INT NOT NULL UNIQUE AUTO_INCREMENT,
    Name VARCHAR(64) NOT NULL
    PRIMARY KEY (Name)
)

Теперь вы можете иметь несколько ролей на пользователя и использовать такие запросы, как

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`

Что даст вам основные User данные и разделенный запятыми список всех назначенных Role имен.

В общем, лучший способ нормализовать структуру базы данных - сделать таблицы как можно более общими, не создавая избыточности, поэтому не добавляйте подробные данные администратора или клиента в пользовательскую таблицу, а используйте соотношение между User и Administrator, чтобы найти конкретные данные администратора. То, как вы делаете это сейчас, не очень нормализовано.

Я посмотрю, смогу ли я найти свою любимую книгу по нормализации базы данных и опубликую ISBN, когда у меня будет время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...