2012-02-17 2 views
2

Я новичок в MySQL и только что узнал о важности нормализации данных. Моя база данных имеет простую структуру:Нормализация данных 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 и возвращаю обратно в таблицу как набор словарей. И этот процесс повторяется каждый раз при составлении новой заметки. Есть лучший способ сделать это? Возможно, данные пользователя должны быть таблицей, причем каждая строка является запиской, но я не совсем уверен, как это будет работать?

+0

Как вы используете данные JSON? –

+0

Это приложение для заметок iPhone. Данные - это всего лишь массив примечаний пользователя в формате JSON. – Snowman

ответ

2

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

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

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

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

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

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

Обновление: основываясь на вашем объяснении хранящихся данных и способах его использования, вы, вероятно, захотите нормализовать его. Что-то вроде следующего:

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

Обратите внимание, насколько больше вы можете сделать с нормированными данными, и как легко это? Тривиально найти, обновить, добавить или удалить какой-либо конкретный компонент.

+0

Мое приложение никогда не понадобилось бы делать какие-либо причудливые поиски или сортировку в db, ему просто нужно получить строку данных JSON для определенного адреса электронной почты, преобразовать ее в массив, и приложение будет знать, что с ним делать. Так говорят в моей таблице выше, у меня 500 000 пользователей, и я хочу получить поле данных для электронной почты: [email protected] Будет ли повлиять на производительность этого запроса на то, нормализованы ли мои данные или нет? Или моя нынешняя структура отлично подходит для этой ситуации? – Snowman

+1

Определенно нормализуется. С реляционными базами данных, если вы не знаете, нормализуется или не нормализуется, вы должны обязательно нормализовать. –

+0

Можете ли вы объяснить разницу в этом запросе, нормализованы ли мои данные или нет? – Snowman

1

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

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

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

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

+2

«нормализация не улучшает скорость» - это * определенно * должно быть квалифицировано. Иногда это правда, иногда это не так. –

+0

Нормализация и скорость ... А старые дебаты. если бы у меня была таблица с 50 текстовыми полями, которые можно было бы нормализовать в несколько таблиц, она, безусловно, будет быстрее нормализована, если я буду искать только 1 из полей. – iWantSimpleLife

+0

См. Редактирование ... – Snowman

1

Основным преимуществом нормализации является устранение избыточных данных, но поскольку данные каждого пользователя уникальны для этого пользователя, нет никакой пользы для разделения этой таблицы и нормализации. Кроме того, поскольку в интерфейсе используются словари как объекты 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); 
+0

См. Правки ... – Snowman

+0

Oh. Таким образом, для каждого пользователя может быть много заметок, и несколько пользователей могут указать один и тот же заголовок и автора? Могут ли пользователи изменять существующую заметку или добавлять заметки? –

+0

У каждого пользователя есть свои личные заметки. Они действительно могут изменять, удалять и добавлять примечания. – Snowman

0

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

Смежные вопросы