索引优化分析_预热_JOIN

1.性能下降SQL慢 执行时间长 等待时间长

  1. 数据过多——分库分表 mycat
  2. 索引失效,没有充分利用到索引——索引建立
  3. 关联查询太多join(设计缺陷或不得已的需求)——SQL优化
  4. 服务器调优及各个参数设置(缓冲、线程数等)——调整my.cnf

2.常见通用的Join查询

2.1.SQL执行顺序

1.手写
在这里插入图片描述

2.机读
随着MySQL版本的更新换代,其优化器也在不断的升级,优化器会分析不同执行顺序产生的性能消耗不同而动态调整执行顺序。
下面是经常出现的查询顺序:
在这里插入图片描述
3.总结(鱼骨图)
在这里插入图片描述

2.2.Join图

在这里插入图片描述

2.3.建表SQL

CREATE TABLE `t_dept` (
 `id` INT(11) NOT NULL AUTO_INCREMENT,
 `deptName` VARCHAR(30) DEFAULT NULL,
 `address` VARCHAR(40) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
CREATE TABLE `t_emp` (
 `id` INT(11) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(20) DEFAULT NULL,
 `age` INT(3) DEFAULT NULL,
 `deptId` INT(11) DEFAULT NULL,
`empno` INT(11) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `idx_dept_id` (`deptId`)
 #CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `t_dept` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO t_dept(id,deptName,address) VALUES(1,'华山','华山');
INSERT INTO t_dept(id,deptName,address) VALUES(2,'丐帮','洛阳');
INSERT INTO t_dept(id,deptName,address) VALUES(3,'峨眉','峨眉山');
INSERT INTO t_dept(id,deptName,address) VALUES(4,'武当','武当山');
INSERT INTO t_dept(id,deptName,address) VALUES(5,'明教','光明顶');
INSERT INTO t_dept(id,deptName,address) VALUES(6,'少林','少林寺');

INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(1,'风清扬',90,1,100001);
INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(2,'岳不群',50,1,100002);
INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(3,'令狐冲',24,1,100003);

INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(4,'洪七公',70,2,100004);
INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(5,'乔峰',35,2,100005);

INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(6,'灭绝师太',70,3,100006);
INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(7,'周芷若',20,3,100007);

INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(8,'张三丰',100,4,100008);
INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(9,'张无忌',25,5,100009);
INSERT INTO t_emp(id,NAME,age,deptId,empno) VALUES(10,'韦小宝',18,NULL,100010);

2.4 7种JOIN

  1. A、B两表共有(查询所有有部门的员工->员工和部门之间必须存在关联的数据)
SELECT * FROM t_emp a INNER JOIN t_dept b ON a.deptid = b.id ;

在这里插入图片描述2. A、B两表共有+A的独有(列出所有用户,并显示其机构信息)A的全集

 SELECT * FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id ;

在这里插入图片描述
3. A、B两表共有+B的独有(列出所有部门,并显示其部门的员工信息 )B的全集

SELECT * FROM t_emp a RIGHT JOIN t_dept b ON a.deptid = b.id ;

在这里插入图片描述
4. A的独有 (查询没有加入任何部门的员工)

SELECT * FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id WHERE b.id IS NULL ;

在这里插入图片描述
5. B的独有(查询没有任何员工的部门)

SELECT * FROM t_emp a RIGHT JOIN t_dept b ON a.deptid = b.id WHERE a.id IS NULL ;

在这里插入图片描述
6. AB全有(查询所有员工和所有部门)
#MySQL Full Join的实现 因为MySQL不支持FULL JOIN,下面是替代方法
#left join + union(去重)+ right join

SELECT * FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id 
UNION 
SELECT * FROM t_emp a RIGHT JOIN t_dept b ON a.deptid = b.id ;

在这里插入图片描述
在这里插入图片描述

SELECT * FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id 
UNION ALL
SELECT * FROM t_emp a RIGHT JOIN t_dept b ON a.deptid = b.id ;

1.UNION ALL 不会自动去重。
2.UNION在使用时,两张表的字段保证一致,如果不一致,请在slect后面列选字段,不要使用*
在这里插入图片描述
7. A的独有+B的独有(查询没有加入任何部门的员工,以及查询出部门下没有任何员工的部门)

SELECT * FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id WHERE b.id IS NULL 
UNION 
SELECT * FROM t_emp a RIGHT JOIN t_dept b ON a.deptid = b.id WHERE a.id IS NULL ;

2.5.扩展(掌门人)

1.增加掌门人字段

ALTER TABLE t_dept ADD CEO INT(11);
UPDATE t_dept SET CEO=2 WHERE id=1;
UPDATE t_dept SET CEO=4 WHERE id=2;
UPDATE t_dept SET CEO=6 WHERE id=3;
UPDATE t_dept SET CEO=8 WHERE id=4;
UPDATE t_dept SET CEO=9 WHERE id=5;

2.求各个门派对应的掌门人名称

SELECT b.deptname,a.name FROM t_dept b LEFT JOIN t_emp a ON b.ceo = a.id ;

3.求所有当上掌门人的平均年龄:

SELECT AVG(a.age) FROM t_emp a INNER JOIN t_dept b ON a.id = b.ceo ;

4.求所有人,对应的掌门是谁(4种写法分析)

#临时表连接方式  
#step1根据ceo 去查找每个部门的掌门是谁
{SELECT b.id AS deptId,a.name AS ceoname FROM t_emp a INNER JOIN t_dept b ON a.id = b.ceo }
#step2 与员工表整合
SELECT c.name,ab.ceoname FROM t_emp c LEFT JOIN
( SELECT b.id AS deptId,a.name AS ceoname FROM t_emp a INNER JOIN t_dept b ON a.id = b.ceo ) ab
ON c.deptId = ab.deptId ;
 
#临时表连接方式 根据员工id查找
#step1 根据部门Id 查询员工的信息
SELECT a.name,b.ceo FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id 
# step2 与员工表整合
SELECT ab.name,c.name AS ceoname FROM 
( SELECT a.name,b.ceo FROM t_emp a LEFT JOIN t_dept b ON a.deptid = b.id ) ab
LEFT JOIN t_emp c ON ab.ceo = c.id ;
 
#三表左连接方式
SELECT a.name,c.name AS ceoname FROM t_emp a 
LEFT JOIN t_dept b ON a.deptid = b.id 
LEFT JOIN t_emp c ON b.ceo = c.id ;
 
#子查询方式
SELECT a.name ,(SELECT c.name FROM t_emp c WHERE c.id=b.ceo) AS ceoname
FROM t_emp a LEFT JOIN t_dept b 
ON a.deptid = b.id ;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值