SQL有外连接的时候注意过滤条件位置否则会导致网页慢

奶奶的,为啥现在五一节只放3天,5月的天气最适合出游了,不过俺们这些苦逼的IT男是没法享受了。
一来到公司,项目经理就找到开发leader,说我们网站 页面很慢,让他排查原因。
一听说 网站慢,页面慢哥就来精神了,哥的老本行就是 解决“慢”的问题。
开发leader 很郁闷的说,我们已经加了 memcache了,20分钟 cache一次,咋个还是慢呢,
于是哥就问,那个网页跑了哪些SQL? 能抓出来让我看看吗? 开发Leader 果断的把SQL 抓了出来。
经过排查,我们发现了一个SQL确实跑得慢。该SQL 如下


代码如下:

select *
from (select u.NAME UniversityName,
u.id UniversityId,
count(a.SIGNUPNUMBER) playercnt
from T_B_UNIVERSITY u
left join T_D_EDUCATION e
on e.UNIVERSITY_ID = u.id
left join T_D_VIDEO_PLAYER a
on a.USER_ID = e.user_id
and e.ISDEFAULT = 1
and e.ISVALID = 1
and a.AUDITSTATUS = 1
and a.ISVALID = 1
left join T_D_USER c
on a.USER_ID = c.id
and c.ISVALID = 1
where u.REGION_CODE like '43%'
group by u.NAME, u.id)
order by playercnt desc;

执行计划如下


代码如下:

执行计划
----------------------------------------------------------
Plan hash value: 3938743742
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 142 | 10366 | 170 (3)| 00:00:03 |
| 1 | SORT ORDER BY | | 142 | 10366 | 170 (3)| 00:00:03 |
| 2 | HASH GROUP BY | | 142 | 10366 | 170 (3)| 00:00:03 |
|* 3 | HASH JOIN RIGHT OUTER| | 672 | 49056 | 168 (2)| 00:00:03 |
|* 4 | TABLE ACCESS FULL | T_D_USER | 690 | 5520 | 5 (0)| 00:00:01 |
| 5 | NESTED LOOPS OUTER | | 672 | 43680 | 162 (1)| 00:00:02 |
|* 6 | HASH JOIN OUTER | | 672 | 37632 | 14 (8)| 00:00:01 |
|* 7 | TABLE ACCESS FULL | T_B_UNIVERSITY | 50 | 2050 | 8 (0)| 00:00:01 |
| 8 | TABLE ACCESS FULL | T_D_EDUCATION | 672 | 10080 | 5 (0)| 00:00:01 |
| 9 | VIEW | | 1 | 9 | 0 (0)| 00:00:01 |
|* 10 | FILTER | | | | | |
|* 11 | TABLE ACCESS FULL| T_D_VIDEO_PLAYER | 1 | 15 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("A"."USER_ID"="C"."ID"(+))
4 - filter("C"."ISVALID"(+)=1)
6 - access("E"."UNIVERSITY_ID"(+)="U"."ID")
7 - filter("U"."REGION_CODE" LIKE '43%')
10 - filter("E"."ISVALID"=1 AND "E"."ISDEFAULT"=1)
11 - filter("A"."USER_ID"="E"."USER_ID" AND "A"."AUDITSTATUS"=1 AND
"A"."ISVALID"=1)

大家能发现这个SQL 的问题吗? 这个 SQL 之所以跑得慢是因为开发人员把SQL的条件写错位置了
正确的写法应该是 下面这样的


代码如下:

select *
from (select u.NAME UniversityName,
u.id UniversityId,
count(a.SIGNUPNUMBER) playercnt
from T_B_UNIVERSITY u
left join T_D_EDUCATION e
on e.UNIVERSITY_ID = u.id
and e.ISDEFAULT = 1
and e.ISVALID = 1
left join T_D_VIDEO_PLAYER a
on a.USER_ID = e.user_id
and a.AUDITSTATUS = 1
and a.ISVALID = 1
left join T_D_USER c
on a.USER_ID = c.id
and c.ISVALID = 1
where u.REGION_CODE like '43%'
group by u.NAME, u.id)
order by playercnt desc;

执行计划如下


代码如下:

执行计划
----------------------------------------------------------
Plan hash value: 2738827747
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 142 | 11218 | 25 (16)| 00:00:01 |
| 1 | SORT ORDER BY | | 142 | 11218 | 25 (16)| 00:00:01 |
| 2 | HASH GROUP BY | | 142 | 11218 | 25 (16)| 00:00:01 |
|* 3 | HASH JOIN RIGHT OUTER | | 301 | 23779 | 23 (9)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | T_D_USER | 690 | 5520 | 5 (0)| 00:00:01 |
|* 5 | HASH JOIN RIGHT OUTER| | 301 | 21371 | 17 (6)| 00:00:01 |
|* 6 | TABLE ACCESS FULL | T_D_VIDEO_PLAYER | 78 | 1170 | 3 (0)| 00:00:01 |
|* 7 | HASH JOIN OUTER | | 301 | 16856 | 14 (8)| 00:00:01 |
|* 8 | TABLE ACCESS FULL | T_B_UNIVERSITY | 50 | 2050 | 8 (0)| 00:00:01 |
|* 9 | TABLE ACCESS FULL | T_D_EDUCATION | 301 | 4515 | 5 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("A"."USER_ID"="C"."ID"(+))
4 - filter("C"."ISVALID"(+)=1)
5 - access("A"."USER_ID"(+)="E"."USER_ID")
6 - filter("A"."AUDITSTATUS"(+)=1 AND "A"."ISVALID"(+)=1)
7 - access("E"."UNIVERSITY_ID"(+)="U"."ID")
8 - filter("U"."REGION_CODE" LIKE '43%')
9 - filter("E"."ISDEFAULT"(+)=1 AND "E"."ISVALID"(+)=1)

之前SQL要跑至少5秒以上,现在0.1秒能出结果。
各位童鞋,SQL 有外连接的时候,要注意过滤条件的位置,记住啦!!!
有SQL 需要优化的 欢迎加入 QQ 群 220761024 申请注明 来自CSDN

(0)

相关推荐

  • SQL有外连接的时候注意过滤条件位置否则会导致网页慢

    奶奶的,为啥现在五一节只放3天,5月的天气最适合出游了,不过俺们这些苦逼的IT男是没法享受了. 一来到公司,项目经理就找到开发leader,说我们网站 页面很慢,让他排查原因. 一听说 网站慢,页面慢哥就来精神了,哥的老本行就是 解决"慢"的问题. 开发leader 很郁闷的说,我们已经加了 memcache了,20分钟 cache一次,咋个还是慢呢, 于是哥就问,那个网页跑了哪些SQL? 能抓出来让我看看吗? 开发Leader 果断的把SQL 抓了出来. 经过排查,我们发现了一个SQ

  • 深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接

    1.内联接(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接.     内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 students和courses表中学生标识号相同的所有行.       2.外联接.外联接可以是左向外联接.右向外联接或完整外部联接.     在 FROM子句中指定外联接时,可以由下列几组关键字中的一组指定:     1)LEFT  JOIN或LEFT OUTER JOIN     左向外联接的结果集包括  LEF

  • SQL语句的并集UNION 交集JOIN(内连接,外连接)等介绍

    1. a. 并集UNION SELECT column1, column2 FROM table1 UNION SELECT column1, column2 FROM table2 b. 交集JOIN SELECT * FROM table1 AS a JOIN table2 b ON a.name=b.name c. 差集NOT IN SELECT * FROM table1 WHERE name NOT IN(SELECT name FROM table2) d. 笛卡尔积 SELECT

  • SQL 四种连接-左外连接、右外连接、内连接、全连接详解

    SQL的四种连接-左外连接.右外连接.内连接.全连接 今天在看一个遗留系统的数据表的时候发现平时查找的视图是FULL OUT JOIN的,导致平时的数据记录要进行一些限制性处理,其实也可以设置视图各表为右外连接并在视图上设置各列的排序和筛选条件就可以达到效果. 联接条件可在FROM或WHERE子句中指定,建议在FROM子句中指定联接条件.WHERE和HAVING子句也可以包含搜索条件,以进一步筛选联接条件所选的行. 联接可分为以下几类: 1.内联接(典型的联接运算,使用像 =  或 <> 之类

  • sql表连接查询使用方法(sql多表连接查询)

    实际的项目,存在多张表的关联关系.不可能在一张表里面就能检索出所有数据.如果没有表连接的话,那么我们就需要非常多的操作.比如需要从A表找出限制性的条件来从B表中检索数据.不但需要分多表来操作,而且效率也不高.比如书中的例子: 复制代码 代码如下: SELECT FIdFROM T_CustomerWHERE FName='MIKE' 这个SQL语句返回2,也就是姓名为MIKE 的客户的FId值为2,这样就可以到T_Order中检索FCustomerId等于2 的记录: 复制代码 代码如下: SE

  • SQL语句过滤条件放在on与where子句中的区别和联系浅析

    目录 摘要: 综述 过滤条件放在on和where中的区别 小结 Reference 摘要: 介绍在多表关联SQL语句中,过滤条件放在on和where子句中的区别——inner join中没区别,外连接就不一样. 综述 蚂蚁金服的一道SQL面试题如下:SQL语句中,过滤条件放在on和where子句中的区别.当时满脑子是left join和inner join等,觉得没区别啊!细思极恐,故梳理一下. 过滤条件放在on和where中的区别 数据库在通过连接两张或多张表来查询记录时,都会先通过join

  • SQL多表连接查询实例分析(详细图文)

    新建两张表: 表1:student  截图如下: 表2:course  截图如下: (此时这样建表只是为了演示连接SQL语句,当然实际开发中我们不会这样建表,实际开发中这两个表会有自己不同的主键.) 一.外连接外连接可分为:左连接.右连接.完全外连接. 1.左连接  left join 或 left outer join SQL语句:select * from student left join course on student.ID=course.ID执行结果: 左外连接包含left joi

  • sql 多表连接查询

    新建两张表: 表1:student  截图如下: 表2:course  截图如下: (此时这样建表只是为了演示连接SQL语句,当然实际开发中我们不会这样建表,实际开发中这两个表会有自己不同的主键.) 一.外连接外连接可分为:左连接.右连接.完全外连接. 1.左连接  left join 或 left outer join SQL语句:select * from student left join course on student.ID=course.ID执行结果: 左外连接包含left joi

  • SQL中过滤条件放on和where中的区别详解

    前言 今天接到蚂蚁金服的电面,问了sql中过滤条件放在on和where中的区别,当时满脑子是inner join,觉得没区别啊.后来才想起来,连接查询除了inner join还有right join,left join.汗呐,当时还是太紧张了.这里做一下记录吧. join过程可以这样理解:首先两个表做一个笛卡尔积,on后面的条件是对这个笛卡尔积做一个过滤形成一张临时表,如果没有where就直接返回结果,如果有where就对上一步的临时表再进行过滤.下面看实验: 先准备两张表: 先执行inner

  • SQL的各种连接Join案例详解

    最常见的 JOIN 类型:SQL INNER JOIN(简单的 JOIN).SQL LEFT JOIN.SQL RIGHT JOIN.SQL FULL JOIN,其中前一种是内连接,后三种是外链接. 假设我们有两张表,Table A是上边的表,Table B是下边的表. Table A id name 1 Google 2 淘宝 3 微博 4 Facebook Table B id address 1 美国 5 中国 3 中国 6 美国 一.INNER JOIN 内连接是最常见的一种连接,只连接

随机推荐