这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战
前言: 本篇文章 是我关于MySQL的第28篇文章,水平一般、能力有限。文章写的比较浅,适合新手来看。
反范式
首先我们看一个例子:
街上新开了一家面馆,面馆有汤面和炒面。汤面统一价格是13元,炒面统一价格是15元。汤面里有牛肉拉面,西红柿鸡丝面。炒面有蛋炒面和尖椒炒面。我们来设计一份表。
CREATE TABLE `noodle` (
`name` varchar(100) NOT NULL COMMENT '名称',
`type` varchar(100) NOT NULL COMMENT '种类',
`price` int NOT NULL COMMENT '价格'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='拉面信息';
select * from noodle;
name |type|price|
-----+----+-----+
蛋炒面 |炒面 | 15|
尖椒炒面 |炒面 | 15|
牛肉面 |汤面 | 13|
鸡蛋肉丝面|汤面 | 13|
上面这种设计形式就是反范式,其将包含有传递数据的所有数据都写在一张表中。简单直接。 我们可以直观的看到 名称-种类-价格之间的关联关系。但是有冗余数据不可避免。
范式
还是上面的例子,我们直接来设计表结构。这次将传递数据分离开来。
CREATE TABLE `noodle` (
`name` varchar(100) NOT NULL COMMENT '名称',
`type` varchar(100) NOT NULL COMMENT '种类',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='拉面信息';
CREATE TABLE `noodle_type` (
`type` varchar(100) NOT NULL COMMENT '种类',
`price` int NOT NULL COMMENT '价格'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='拉面种类信息';
select * from noodle;
name |type|
-----+----+
蛋炒面 |炒面 |
尖椒炒面 |炒面 |
牛肉面 |汤面 |
鸡蛋肉丝面|汤面 |
select * from noodle_type;
name |type|price|
-----+----+-----+
炒面 | 15|
汤面 | 13|
上面这种设计形式就是范式,每张表都是单独的。没有冗余数据和传递依赖。每次修改炒面价格的时候只需要修改type表。而不是像反范式一样修改每一行炒面的价格。
总结
设计数据库表时,一定要灵活。没必要将所有表都拆的零碎。但是也没必要将所有的数据都写到一张表中,几十列反而不方便查询数据。将范式和反范式相结合才是最好的设计方式。