zoukankan      html  css  js  c++  java
  • MYSQL使用外键进行优化

    #转载请联系

    假如你是京东的数据库管理员,你现在管理着这样一个数据库。

    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.不要数据库层面去验证!数据库直接插入,不要外键!可以用前面两个方法的任意一个保证插入的数据满足要求。


    个人的经验是在一些不常常改变数据的小表上,又是比较基础的数据上使用外键。

  • 相关阅读:
    Struts2【UI标签、数据回显、资源国际化】
    Struts2【配置】知识要点
    Struts2与Spring整合
    Struts2入门这一篇就够了
    Hibernate最全面试题
    Hibernate【查询、连接池、逆向工程】
    Hibernate【缓存】知识要点
    Hibernate【inverse和cascade属性】知识要点
    输入法设置,SublimeTest,putty掉线
    Hibernate【映射】知识要点
  • 原文地址:https://www.cnblogs.com/chichung/p/9589257.html
Copyright © 2011-2022 走看看