规范化MySQL数据

时间:2012-02-17 00:46:13

标签: mysql normalization

我是MySQL的新手,刚刚了解了数据规范化的重要性。我的数据库结构简单:

我有一个名为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 个答案:

答案 0 :(得分:2)

您所有问题的答案实际上取决于JSON数据的用途,以及您是否需要使用该数据的某些属性来确定返回哪些行。

如果您的数据确实没有架构,并且您实际上只是使用它来存储将由知道如何通过某些其他条件(例如其他字段之一)检索正确行的应用程序使用的数据每次都没有理由将它存储为除应用程序期望之外的任何其他内容(在本例中为JSON)。

如果JSON数据包含一些对所有条目都相同的结构,并且如果直接从数据库查询此数据很有用,那么您可能希望创建一个或多个表(或者可能只是一些字段)持有这些数据。

作为一个实际示例,如果数据字段包含阵列中该用户的JSON枚举服务,并且每个服务都具有唯一的ID,类型和价格,您可能需要一个包含以下字段的单独表(使用你自己的命名约定):

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 :(得分:1)

规范化是一种哲学。有些人认为它适合他们的数据库方法,有些则不然。许多现代数据库解决方案甚至专注于非规范化以提高速度。

标准化通常不会提高速度。但是,它极大地提高了访问和写入数据的简单性。例如,如果要添加请求,则必须编写一个全新的JSON字段。如果它已标准化,您只需向表中添加一行即可。

在规范化中,“JSON字符串格式的字典数组”总是很糟糕。字典数组可以翻译为行列表,这是一个表。

如果您是数据库的新手:NORMALIZE。非规范化是专业人士的事情。

答案 2 :(得分: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);  

答案 3 :(得分:0)

在您的情况下,我将抽象出处理此表的类。然后保持数据标准化。如果将来,数据访问模式发生变化,我需要对数据进行规范化,我只需这样做,对程序的影响就会减少。我只需要更改处理这组数据的类来查询规范化的表,但返回数据就像数据库结构永远不会改变一样。