- A+
1.1. 前言
作为公司的DB一个职责就是和开发沟通,并给出一些编写SQL的建议。但是沟通容易需要达成一致却是比较困难的。基本上在系统中对数据库的查询疯狂的使用到join进行。夸张的一条语句格式化后竟然有100多行,其中个总子查询中套子查询,join中套join(能写出这种SQL的也算的上是“大神”了 ^_^),这种语句我再之前的MySQL数据库中是重来没碰到过的(当然,在Oracle中还是时不时的会有)。然而这些语句竟然还是执行的比较多的。因此当访问上来的时候应用程序和数据库慢的更乌龟一样,CPU也在报警。严重影响到了系统。解析了一下SQL大部分时间都是花在SQL解析上面。不知道的人,总是说这CPU真垃圾,需要增加CPU(你好多钱哦,用MySQL和用Oracle一样)。解决办法就是将这些SQL进行拆解成简单的SQL。运行起来就顺利了。借着这件事。和开发负责人将类似的SQL都找出来,一并优化了。
之后我的建议是,能不能在系统中之后的开发不用join。原因是:不用jion之后能对系统的扩展和二次开发有帮助。重要的是能为能提高系统和数据库的并发。
程序员的接口总是那么的统一和一致:这样我们的开发量会大大提高,会影响进度。这时候我有什么好说的呢?毕竟公司的命脉就在与产品,产品都出不了。那不就值糟糕了。于是只能是默默的达成尽量不写复杂SQL。
1.2. 疑问
真的写简单的SQL就会降低开发效率么?真的就会增加工作量么?
1.3. 证明
本着拥有一点点开发经验,来打破他们说的会增加工作量,会降低开发效率。
1.4. 说明
一下代码都是使用Python来实现。
为了阅读的分层次我使用5个章节来说明我的代码。
1.5. 数据库环境构建
本示例使用了4个表如下表:
表名 | 备注 |
user | 用户表 |
orders | 订单表 |
order_good | 订单商品表 |
coupon | 券表 |
以下是创建表和表数据的SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
-- 创建test数据库 CREATE database test; USE test; -- 创建用户信息 CREATE TABLE `user` ( `user_id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `user` VALUES (10,'HH'); -- 创建订单信息 CREATE TABLE `orders` ( `order_id` int(11) DEFAULT NULL, `num` int(11) DEFAULT NULL, `user_id` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `orders` VALUES (1,11111,10), (2,22222,10), (3,33333,10), (4,44444,10), (5,55555,10); -- 创建订单商品信息 CREATE TABLE `order_good` ( `id` int(11) DEFAULT NULL, `order_id` int(11) DEFAULT NULL, `good_name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `order_good` VALUES (3,2,'order_good_3'), (4,2,'order_good_4'), (5,3,'order_good_5'), (6,3,'order_good_6'), (7,4,'order_good_7'), (8,4,'order_good_8'), (9,5,'order_good_9'), (10,5,'order_good_10'), (1,1,'order_good_1'), (2,1,'order_good_2'); -- 创建券信息 CREATE TABLE `coupon` ( `coupon_id` int(11) DEFAULT NULL, `order_id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `coupon` VALUES (1,1,'coupon_1'), (2,3,'coupon_3'), (3,5,'coupon_5'); |
SQL文件(没有带DROP database):test_db
1.6. Join查询拆解
在一般的时候大家都认为使用jion能在数据库找到自己想要到记录,如下面我们需要查询订单的相关信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
------------------ -- 查找订单信息 -- ------------------ SELECT u.name AS '用户名', o.num AS '订单号', og.good_name AS '购买的商品名称', c.name AS '券名字' FROM user AS u LEFT JOIN orders AS o ON u.user_id = o.user_id LEFT JOIN order_good AS og ON o.order_id = og.order_id LEFT JOIN coupon AS c ON o.order_id = c.order_id WHERE u.user_id = 10; +-----------+-----------+-----------------------+-----------+ | 用户名 | 订单号 | 购买的商品名称 | 券名字 | +-----------+-----------+-----------------------+-----------+ | HH | 11111 | order_good_1 | coupon_1 | | HH | 11111 | order_good_2 | coupon_1 | | HH | 33333 | order_good_5 | coupon_3 | | HH | 33333 | order_good_6 | coupon_3 | | HH | 55555 | order_good_9 | coupon_5 | | HH | 55555 | order_good_10 | coupon_5 | | HH | 22222 | order_good_3 | NULL | | HH | 22222 | order_good_4 | NULL | | HH | 44444 | order_good_7 | NULL | | HH | 44444 | order_good_8 | NULL | +-----------+-----------+-----------------------+-----------+ |
如果将join拆分之后,就变成了4条简单的语句。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
---------------------- -- 分 查找订单信息 -- ---------------------- -- 通过 用户ID 获得用户名 SELECT user_id, name FROM user WHERE user_id = 10; -- 通过 用户ID 获得订单信息 SELECT order_id, num FROM orders WHERE user_id = 10; -- 通过上面获得的 订单ID 获得商品订单信息。 SELECT order_id, good_name FROM order_good WHERE order_id IN (1,2,3,4,5); -- 通过 订单ID 获得券信息 SELECT order_id, name FROM coupon WHERE order_id IN(1,2,3,4,5); |
这时候就有人会说了将语句给查分了的结构都还不是最终结果。这里我只能说确实是这样。最终结果我们需要在应用程序中将他拼凑出来。
昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)
感觉本文内容不错,读后有收获?

22/02/2017 下午 3:33 沙发
新浪微博就是禁止使用JOIN,并发量大后JOIN绝对会拖死数据库!
16/04/2016 上午 12:24 板凳
非常有道理