Нормализация данных MySQL - PullRequest
       8

Нормализация данных MySQL

3 голосов
/ 17 февраля 2012

Я новичок в MySQL, и только что узнал о важности нормализации данных.Моя база данных имеет простую структуру:

У меня есть 1 таблица с именем users с полями:

userName (string)
userEmail (string)
password (string)
requests (an array of dictionaries in JSON string format)
data (another array of dictionaries in JSON string format)
deviceID (string)

Сейчас это моя структура.Будучи очень новым для MySQL, я действительно не понимаю, почему моя вышеупомянутая структура - плохая идея?Зачем мне нужно нормализовать это и составить отдельные таблицы?Это первый вопрос - почему?(Некоторые также говорят, что не следует помещать JSON в мою таблицу. Почему или почему нет?)

Второй вопрос: как?С вышеупомянутой структурой, сколько таблиц я должен иметь, и что будет в каждой таблице?

Редактировать: Так что, возможно, нормализация здесь не является абсолютно необходимой, но, может быть, есть лучший способ реализовать мое поле данных?Поле data представляет собой массив словарей: каждый словарь - это просто элемент заметки с несколькими ключами (заголовок, автор, дата, тело).Итак, что я делаю сейчас, что, на мой взгляд, может быть неэффективно, каждый раз, когда пользователь создает новую заметку, я отправляю эту заметку из своего приложения в PHP для обработки.Я получаю массив словарей JSON, уже являющийся частью данных этого пользователя, я преобразую его в массив PHP, затем добавляю в конец этого массива новую заметку, преобразую все это обратно в JSON и помещаю обратно в таблицу.как массив словарей.И этот процесс повторяется каждый раз, когда создается новая заметка.Есть лучший способ сделать это?Может быть, данные пользователя должны быть таблицей, где каждая строка является примечанием, но я не совсем уверен, как это будет работать?

Ответы [ 4 ]

3 голосов
/ 17 февраля 2012

Ответ на все ваши вопросы действительно зависит от того, для чего нужны данные JSON, и от того, понадобится ли вам когда-либо использовать какое-либо свойство этих данных, чтобы определить, какие строки возвращаются.

Если ваши данные действительно не имеют схемы, и вы действительно просто используете ее для хранения данных, которые будут использоваться приложением, которое знает, как извлечь правильную строку по некоторым другим критериям (например, одному из других полей) каждый раз нет причин хранить его как что-либо кроме того, что ожидает его приложение (в данном случае, JSON).

Если данные JSON содержат некоторую структуру, одинаковую для всех записей, и если полезно запрашивать эти данные непосредственно из базы данных, вы можете создать одну или несколько таблиц (или, может быть, просто несколько дополнительных полей) для держать эти данные.

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

serviceId (integer)
userName (string)
serviceType (string)
servicePrice (float)

И каждый сервис для этого пользователя получит свою собственную запись. Затем вы можете запросить пользователей, у которых есть конкретный сервис, что в зависимости от ваших потребностей может быть очень полезным. В дополнение к простым запросам, индексирование определенных полей отдельных таблиц также может привести к очень БЫСТРЫМ запросам.

Обновление: основываясь на вашем объяснении хранимых данных и способах их использования, вы, вероятно, хотите, чтобы они были нормализованы. Примерно так:

# user table
userId (integer, auto-incrementing)
userName (string)
userEmail (string)
password (string)
deviceID (string)

# note table
noteId (integer, auto-incrementing)
userId (integer, matches user.userId)
noteTime (datetime)
noteData (string, possibly split into separate fields depending on content, such as subject, etC)

# request table
requestId (integer, auto-incrementing)
userId (integer, matches user.userId)
requestTime (datetime)
requestData (string, again split as needed)

Затем вы можете запросить примерно так:

# Get a user
SELECT * FROM user WHERE userId = '123';
SELECT * FROM user WHERE userNAme = 'foo';

# Get all requests for a user
SELECT * FROM request WHERE userId = '123';
# Get a single request
SELECT * FROM request WHERE requestId = '325325';

# Get all notes for a user
SELECT * FROM note WHERE userId = '123';
# Get all notes from last week
SELECT * FROM note WHERE userId = '123' AND noteTime > CURDATE() - INTERVAL 1 WEEK;

# Add a note to user 123
INSERT INTO note (noteId, userId, noteData) VALUES (null, 123, 'This is a note');

Обратите внимание, сколько еще вы можете сделать с нормализованными данными, и насколько это просто? Обнаружить, обновить, добавить или удалить любой конкретный компонент тривиально.

1 голос
/ 17 февраля 2012

Основным преимуществом нормализации является устранение избыточных данных, но, поскольку данные каждого пользователя уникальны для этого пользователя, нет смысла разбивать эту таблицу и нормализовать.Кроме того, поскольку интерфейс все равно будет использовать словари в качестве объектов JSON, из-за ненужных усложнений и снижения производительности будут пытаться разложить эти данные.

Хорошо, вот нормализованная модель данных MySQL. Примечание: Вы можете разделить авторов и заголовки на две таблицы для дальнейшего снижения избыточности данных.Вероятно, вы можете использовать похожие методы для «словарей запросов»:

CREATE TABLE USERS(
  UID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  userName varchar(255) UNIQUE,
  password varchar(30),
  userEmail varchar(255) UNIQUE,
  deviceID varchar(255)
) ENGINE=InnoDB;

CREATE TABLE BOOKS(
  BKID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  FKUSERS int, 
  Title varchar(255),
  Author varchar(50)
) ENGINE=InnoDB;
ALTER TABLE BOOKS
  ADD FOREIGN KEY (FKUSERS)
    REFERENCES USERS(UID);

CREATE TABLE NOTES(
  ID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  FKUSERS int, 
  FKBOOKS int,
  Date date,
  Notes text
) ENGINE=InnoDB;

ALTER TABLE NOTES
  ADD FOREIGN KEY BKNO (FKUSERS)
    REFERENCES USERS(UID);
ALTER TABLE NOTES
  ADD FOREIGN KEY (FKBOOKS)
    REFERENCES BOOKS(BKID);  
1 голос
/ 17 февраля 2012

Нормализация - это философия.Некоторые люди думают, что это соответствует их подходу к базе данных, а некоторые нет.Многие современные решения для баз данных даже фокусируются на денормализации для повышения скорости.

Нормализация часто не улучшает скорость.Тем не менее, это значительно улучшает простоту доступа и записи данных.Например, если вы хотите добавить запрос, вам нужно будет написать совершенно новое поле JSON.Если бы он был нормализован, вы могли бы просто добавить строку в таблицу.

При нормализации «массив словарей в формате строки JSON» всегда плох.Массив словарей можно перевести как список строк, который является таблицей.

Если вы новичок в базах данных: NORMALIZE.Денормализация - это что-то для профессионалов.

0 голосов
/ 17 февраля 2012

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

...