假如你是京东的数据库管理员,你现在管理着这样一个数据库。
mysql> select * from goods; +----+---------------------------------------+---------------------+------------+-----------+---------+------------+ | id | name | cate_name | brand_name | price | is_show | is_saleoff | +----+---------------------------------------+---------------------+------------+-----------+---------+------------+ | 1 | r510vc 15.6英寸笔记本 | 笔记本 | 华硕 | 3399.000 | | | | 2 | y400n 14.0英寸笔记本电脑 | 笔记本 | 联想 | 4999.000 | | | | 3 | g150th 15.6英寸游戏本 | 游戏本 | 雷神 | 8499.000 | | | | 4 | x550cc 15.6英寸笔记本 | 笔记本 | 华硕 | 2799.000 | | | | 5 | x240 超极本 | 超级本 | 联想 | 4880.000 | | | | 6 | u330p 13.3英寸超极本 | 超级本 | 联想 | 4299.000 | | | | 7 | svp13226scb 触控超极本 | 超级本 | 索尼 | 7999.000 | | | | 8 | ipad mini 7.9英寸平板电脑 | 平板电脑 | 苹果 | 1998.000 | | | | 9 | ipad air 9.7英寸平板电脑 | 平板电脑 | 苹果 | 3388.000 | | | | 10 | ipad mini 配备 retina 显示屏 | 平板电脑 | 苹果 | 2788.000 | | | | 11 | ideacentre c340 20英寸一体电脑 | 台式机 | 联想 | 3499.000 | | | | 12 | vostro 3800-r1206 台式电脑 | 台式机 | 戴尔 | 2899.000 | | | | 13 | imac me086ch/a 21.5英寸一体电脑 | 台式机 | 苹果 | 9188.000 | | | | 14 | at7-7414lp 台式电脑 linux ) | 台式机 | 宏碁 | 3699.000 | | | | 15 | z220sff f4f06pa工作站 | 服务器/工作站 | 惠普 | 4288.000 | | | | 16 | poweredge ii服务器 | 服务器/工作站 | 戴尔 | 5388.000 | | | | 17 | mac pro专业级台式电脑 | 服务器/工作站 | 苹果 | 28888.000 | | | | 18 | hmz-t3w 头戴显示设备 | 笔记本配件 | 索尼 | 6999.000 | | | | 19 | 商务双肩背包 | 笔记本配件 | 索尼 | 99.000 | | | | 20 | x3250 m4机架式服务器 | 服务器/工作站 | ibm | 6888.000 | | | | 21 | 商务双肩背包 | 笔记本配件 | 索尼 | 99.000 | | | +----+---------------------------------------+---------------------+------------+-----------+
某一天,你boss叫你把商品类型改一下。台式机改为台式电脑。
这时候,你要怎么改呢?
update goods set cate_name="台式电脑" where cate_name='台式机';
???
这样的话,数据表的内部要向查找商品类型为台式机的行,然后再改。改完再找,再改......
这里只是一个示例,只有21条数据。京东上十万百万条数据,这样子操作数据库不忙吗?要知道现在web开发瓶颈都在数据库啊,还要数据库做这么多的工作,你良心不会痛吗?
那么?我要怎么修改呢?
大体思路:我们创建一个商品类型表。然后在goods表设置外键,商品类型用数字来表示。1对应商品类型表的平板电脑,2对应商品类型表的台式机......当我们要修改商品类型是,直接修改商品类型表即可。
1.创建商品类型表
create table if not exists goods_cates(id int unsigned primary key auto_increment,name varchar(40) not null);
2.将商品信息表的商品类型同步到商品类型表
# 注意! 把查询出来的结果写入表的单个字段,不需要加values insert into goods_cates(name) select distinct cate_name from goods; select * from goods_cates; +----+---------------------+ | id | name | +----+---------------------+ | 1 | 笔记本 | | 2 | 游戏本 | | 3 | 超级本 | | 4 | 平板电脑 | | 5 | 台式机 | | 6 | 服务器/工作站 | | 7 | 笔记本配件 | +----+---------------------+
3.将商品信息表的商品类型替换为商品类型表的id
mysql> update goods as g inner join goods_cates as c on g.cate_name=c.name set g.cate_name=c.id; mysql> select * from goods; +----+---------------------------------------+-----------+------------+-----------+---------+------------+ | id | name | cate_name | brand_name | price | is_show | is_saleoff | +----+---------------------------------------+-----------+------------+-----------+---------+------------+ | 1 | r510vc 15.6英寸笔记本 | 1 | 华硕 | 3399.000 | | | | 2 | y400n 14.0英寸笔记本电脑 | 1 | 联想 | 4999.000 | | | | 3 | g150th 15.6英寸游戏本 | 2 | 雷神 | 8499.000 | | | | 4 | x550cc 15.6英寸笔记本 | 1 | 华硕 | 2799.000 | | | | 5 | x240 超极本 | 3 | 联想 | 4880.000 | | | | 6 | u330p 13.3英寸超极本 | 3 | 联想 | 4299.000 | | | | 7 | svp13226scb 触控超极本 | 3 | 索尼 | 7999.000 | | | | 8 | ipad mini 7.9英寸平板电脑 | 4 | 苹果 | 1998.000 | | | | 9 | ipad air 9.7英寸平板电脑 | 4 | 苹果 | 3388.000 | | | | 10 | ipad mini 配备 retina 显示屏 | 4 | 苹果 | 2788.000 | | | | 11 | ideacentre c340 20英寸一体电脑 | 5 | 联想 | 3499.000 | | | | 12 | vostro 3800-r1206 台式电脑 | 5 | 戴尔 | 2899.000 | | | | 13 | imac me086ch/a 21.5英寸一体电脑 | 5 | 苹果 | 9188.000 | | | | 14 | at7-7414lp 台式电脑 linux ) | 5 | 宏碁 | 3699.000 | | | | 15 | z220sff f4f06pa工作站 | 6 | 惠普 | 4288.000 | | | | 16 | poweredge ii服务器 | 6 | 戴尔 | 5388.000 | | | | 17 | mac pro专业级台式电脑 | 6 | 苹果 | 28888.000 | | | | 18 | hmz-t3w 头戴显示设备 | 7 | 索尼 | 6999.000 | | | | 19 | 商务双肩背包 | 7 | 索尼 | 99.000 | | | | 20 | x3250 m4机架式服务器 | 6 | ibm | 6888.000 | | | | 21 | 商务双肩背包 | 7 | 索尼 | 99.000 | | | +----+---------------------------------------+-----------+------------+-----------+---------+------------+
4.这时要注意,商品信息表的数据类型还是原数据类型,但是商品信息表的商品类型已经变为整形,所以我们需要更改一下商品信息表的表结构。
mysql> alter table goods change cate_name cate_id int unsigned not null;
5.添加外键,让cate_id是有含义的。
# 添加外键,指向goods_cates表的id字段 mysql> alter table goods add foreign key(cate_id) references goods_cates(id);
mysql> show create table goods; +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | goods | CREATE TABLE `goods` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(150) NOT NULL, `cate_id` int(10) unsigned NOT NULL, `brand_name` varchar(40) NOT NULL, `price` decimal(10,3) NOT NULL DEFAULT '0.000', `is_show` bit(1) NOT NULL DEFAULT b'1', `is_saleoff` bit(1) NOT NULL DEFAULT b'0', PRIMARY KEY (`id`), KEY `cate_id` (`cate_id`), CONSTRAINT `goods_ibfk_1` FOREIGN KEY (`cate_id`) REFERENCES `goods_cates` (`id`) # 这句就是外键的设置 ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
注意:当数据没有满足外键约束时,无法添加外键!要把没有满足外键约束的行删除才能添加外键。
这样,就完成boss的任务啦。如果要改商品类型的名字,直接在商品类型表改就可以啦~数据库也少了很多负担。
*拓展一下,外键的删除。
mysql> alter table goods drop foreign key goods_ibfk_1; mysql> show create table goods; +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | goods | CREATE TABLE `goods` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(150) NOT NULL, `cate_id` int(10) unsigned NOT NULL, `brand_name` varchar(40) NOT NULL, `price` decimal(10,3) NOT NULL DEFAULT '0.000', `is_show` bit(1) NOT NULL DEFAULT b'1', `is_saleoff` bit(1) NOT NULL DEFAULT b'0', PRIMARY KEY (`id`), KEY `cate_id` (`cate_id`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 | +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
但是!商品信息表还有一个小问题!
如果这个表格主要是查询不怎么会影响效率。
但是如果需要频繁的插入,修改,删除,则会有很大的影响。因为有外键约束,mysql会自己去检测是否符合规则。
如果你要插入十万条数据,mysql会一条一条去检测插入的数据是否满足外键约束。会极大的降低表更新的效率。
这样一来,数据库的工作又沉重了。
那么又应该怎么解决呢?
1.可在数据录入时验证(表示层,ui层),例如网页的选项。
2.在业务层面(python代码)去验证,代码判断输入数据的正确性。
3.不要数据库层面去验证!数据库直接插入,不要外键!前面两个方法任意一个都可以保证插入的数据满足要求。
个人的经验是在一些不常常改变数据的小表上,又是比较基础的数据上使用外键。