1、顺带提一下mysql的sql执行顺序:

FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1
ON: 对虚表VT1进行ON筛选,只有那些符合<join-condition>的行才会被记录在虚表VT2中。
JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。
WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合<where-condition>的记录才会被插入到虚拟表VT4中。
GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.
CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.
HAVING: 对虚拟表VT6应用having过滤,只有符合<having-condition>的记录才会被 插入到虚拟表VT7中。
SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。
DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.
ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,产生虚拟表VT10.
LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

2、创建演示表结构

##用户表
CREATE TABLE `t_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`dept_id` bigint(20) DEFAULT NULL,`user_name` varchar(128) DEFAULT NULL,`password` varchar(255) DEFAULT NULL,`age` int(3) DEFAULT NULL,`telephone` varchar(128) DEFAULT NULL,PRIMARY KEY (`id`),KEY `idx_username_password_age_telephone` (`user_name`,`password`,`age`,`telephone`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
INSERT INTO `mytest`.`t_user`(`id`, `dept_id`, `user_name`, `password`, `age`, `telephone`) VALUES (1, 4, '张董', '***********', 10, '13800000000');
INSERT INTO `mytest`.`t_user`(`id`, `dept_id`, `user_name`, `password`, `age`, `telephone`) VALUES (2, 2, '张董', '***********', 30, '13811111111');
INSERT INTO `mytest`.`t_user`(`id`, `dept_id`, `user_name`, `password`, `age`, `telephone`) VALUES (3, 3, '王经理', '***********', 60, '15200000000');
INSERT INTO `mytest`.`t_user`(`id`, `dept_id`, `user_name`, `password`, `age`, `telephone`) VALUES (4, 2, '王三', '***********', 10, '15211111111');
##部门表
CREATE TABLE `t_dept` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`pid` bigint(20) DEFAULT NULL COMMENT '父级部门ID',`name` varchar(128) DEFAULT NULL COMMENT '部门名称',KEY `idx_id_name` (`id`,`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='部门表';
INSERT INTO `mytest`.`t_dept`(`id`, `pid`, `name`) VALUES (1, 0, '总公司');
INSERT INTO `mytest`.`t_dept`(`id`, `pid`, `name`) VALUES (2, 1, '营销部');
INSERT INTO `mytest`.`t_dept`(`id`, `pid`, `name`) VALUES (3, 1, '企划部');
INSERT INTO `mytest`.`t_dept`(`id`, `pid`, `name`) VALUES (4, 1, '采购部');
##角色表
CREATE TABLE `t_role` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(128) DEFAULT NULL COMMENT '角色名称',`code` varchar(128) DEFAULT NULL COMMENT '角色编码',PRIMARY KEY (`id`),KEY `idx_name_code` (`code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
INSERT INTO `mytest`.`t_role`(`id`, `name`, `code`) VALUES (1, '超级管理员', 'CJGLY');
INSERT INTO `mytest`.`t_role`(`id`, `name`, `code`) VALUES (2, '董事长', 'DSZ');
INSERT INTO `mytest`.`t_role`(`id`, `name`, `code`) VALUES (3, '总经理', 'ZJL');
INSERT INTO `mytest`.`t_role`(`id`, `name`, `code`) VALUES (4, '部门经理', 'BMJL');
INSERT INTO `mytest`.`t_role`(`id`, `name`, `code`) VALUES (5, '普通员工', 'PTYG');
##用户角色关联表
CREATE TABLE `t_user_role` (`user_id` bigint(20) DEFAULT NULL,`role_id` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';
INSERT INTO `mytest`.`t_user_role`(`user_id`, `role_id`) VALUES (1, 1);
INSERT INTO `mytest`.`t_user_role`(`user_id`, `role_id`) VALUES (2, 2);
INSERT INTO `mytest`.`t_user_role`(`user_id`, `role_id`) VALUES (3, 3);
INSERT INTO `mytest`.`t_user_role`(`user_id`, `role_id`) VALUES (4, 4);

3、顺带说下联合查询的条件性能问题:

SELECT u.* FROM t_user u LEFT JOIN t_dept d ON u.dept_id = d.id AND d.`name` = '采购部'  WHERE u.user_name = '张董' ;
SELECT u.* FROM t_user u LEFT JOIN t_dept d ON u.dept_id = d.id WHERE u.user_name = '张董' AND d.`name` = '采购部';

用户表和部门表关联的时候会产生一个笛卡尔积的临时表,如果条件 d.name = ‘采购部’ 在ON后面,那么用户表关联的过滤后的部门表;如果条件 d.name = ‘采购部’ 在WHERE后面,那么用户表关联的是全量部门表数据,再过滤条件;所以关联查询时关联表的条件写在ON后面性能优于WHERE后面;

4、进入正题,联合查询的索引问题

用户表索引(建表时带了 主键索引)

部门表索引(建表时带了 主键索引)

角色表索引(建表时带了 主键索引)

写一个联合SQL看下索引的使用

EXPLAIN
SELECTu.*
FROMt_user uLEFT JOIN t_dept d ON u.dept_id = d.id AND d.`name` = '购部' LEFT JOIN t_user_role ur ON ur.user_id = u.idLEFT JOIN t_role r ON ur.role_id = r.id AND r.`name` = '超级管理员' AND r.`code` = 'GLY'
WHEREu.`user_name` = '张董' AND u.age = 10 AND u.telephone = '13800000000'


这里我们关联了4张表,查询结果出来的4条索引信息,意思是每张表都会根据条件来找自己表的对应的索引;
部门表和角色表用到了主键索引,如果我把表中的主键索引都取掉,看下什么结果:

取掉主键索引之后,部门表和角色表就用到了我们自定义的索引;
所以说,联合查的时候,索引还是各表根据条件找各表的索引
5、说下索引失效的问题,看图就行:
5.1
以部门表来说,LIKE如果有左匹配,部门的索引失效

5.2 以角色表来说,将查询条件的顺序调换成和所建索引的顺序不一样:

虽然条件的顺序和索引的顺序不一样,但是索引依然有效;我们都知道mysql的索引遵循最左匹配原则,mysql的优化器会循环对应表中所有索引,比照查询条件中是否有满足最左匹配索引,正好r.name = ‘超级管理员’ 这个条件满足,所以上面的sql的索引有效,我们在sql中,最佳的是条件顺序和索引顺序保持一致,这样会节省性能。

5.3 以角色表来说,我们删除 r.name = ‘超级管理员’ 这个条件看索引会不会生效

索引没有生效, r.code = 'GLY’没有匹配到任何索引的最左

Mysql的联合查询的索引小结相关推荐

  1. mysql join 联合查询,MySQL连接(join)查询

    1. MySQL连接(join)查询 连接(join)查询是将两个查询的结果以"横向对接"的方式合并起来的结果. 对比:联合查询 是将两个查询的结果以"纵向堆叠" ...

  2. authentication method mysql 8.0查询_mysql 索引整理

    一.MySQL 索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 为何要有索引? ​ 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更 ...

  3. mysql中的强制索引_你如何强制MySQL中的查询使用索引?

    我试图通过向慢查询日志中出现的查询添加索引来提高锤击的wordpress DB的性能. 在MS SQL中,您可以使用查询提示强制查询使用索引,但如果正确覆盖列,则通常很容易获得查询以使用索引. 我有这 ...

  4. mysql 分组联合查询_【MySQL】-2 函数、分组、子查询、联合查询

    函数 Mysql的函数特性没有SQL可移植性强. 大多数情况下支持的函数: 处理文本串的函数: RTrim():处理列值右边的空格 LTrim():处理列值左边的空格 Trim():处理列值的左右两边 ...

  5. 【MySQL】联合查询

    目录 1.前言 2.联合查询 3.内连接和外连接 4.案例演示 4.1 查询篮球哥每科的成绩 4.2 查询所有同学的总成绩及邮箱 5.自连接 5.1 显示所有计算机原理成绩比java成绩高的同学 6. ...

  6. mysql全联合查询,MySQL中的联合查询(内联、左联、外联、右联、全联)

    联合查询效率较高,举例子来说明联合查询:内联inner join .左联left outer join .右联right outer join .全联full outer join 的好处及用法. T ...

  7. MySQL开发技巧——查询、索引和完整性

     目录 第1关 基本查询的学习 查询语句SELECT 头歌实验 查询语句SELECT 第2关 深入学习查询语句 MySQL聚集函数 头歌实验 MySQL聚集函数 第3关 视图的创建和使用 查看数据库中 ...

  8. mysql中联合查询

    联合查询union 一个翻译问题的解释: 在mysql的手册中,将连接查询(Join)翻译为联合查询: 而联合查询(union),没有明确翻译. 但: 在通常的书籍或文章中,join被翻译为" ...

  9. MySql实现联合查询

    SQL实现联合查询 1.笛卡尔积查询(自然查询)-仅供了解 语法格式:select *|字段 from 表1,表2; 查询的结果数量为:表1的数量*表2的数量 2.等值查询-仅供了解 语法格式:sel ...

最新文章

  1. 学习下如何统计【0-9】在任意给定数中出现的次数
  2. 小宝机器人的储存容量_新iPad Pro储存越来越大:甚至到1T!您应该购买哪种存储容量呢?...
  3. 上市公司总市值TOP10出炉,你所在县区看的到未来吗?
  4. vue 版本发布 在线跟新用户操作解决方案_Vue3.0正式发布,本次发布所有总结,一起看看!【附在线视频】...
  5. 从零开始学电脑_带你从零开始学装机 打造自己的专属电脑之固态和机械硬盘搭配篇...
  6. python有趣的代码-python菜鸟教程,python好玩又简单的代码
  7. r语言 怎么把字调大_R语言中的字体调整
  8. Android中OKHttp的基本用法(Get、Post、上传文件等)
  9. android 号码区号判断,android 将手机号中间隐藏为星号(*)和手机号码判断
  10. 计算机cpu天体图,cpu性能天梯排行图 最新的2021年电脑cpu天梯图5月高清图
  11. 卷积神经网络通俗易懂理解
  12. 用VMware克隆CentOS 6.4后修改HWaddr
  13. 刘天佐加盟《经济适用男》 变身木讷IT精英_0
  14. 如何提高数据处理中的准确性
  15. #使用TF实现海龟机器人跟随
  16. Mac升级AS至2021.1.1 patch 2踩坑
  17. 分布式锁-Redis解决方案和Redisson解决方案
  18. 计算机在材料科学中的应用实验心得,计算机在材料科学中的应用.doc
  19. python使用dohq-tfs操作TFS(Team Foundation Server)的Work Item
  20. Python将两个txt文件按行合并

热门文章

  1. 使用Django制作一个电影视频网站--后台界面制作
  2. 高考题能用matlab做吗,全国高考作文三大软件(matlab?工商管理毕业论文题目
  3. FreeRTOS Heap_1、Heap_2、Heap_3、Heap_4、Heap_5的区别
  4. (java版)用邻接表实现无向图的创建
  5. 最大异或对(Tire树)
  6. 【陶晶驰串口屏】stm32h743驱动cubeide配置
  7. 随机突然黑屏重启解决经验分享(华硕主板)
  8. Cannot set up a python SDK Python2.7. The SDK seems invalid.配置问题
  9. 数据填报系统 php源码,自定义数据填报系统
  10. Android系统智能额温枪,智能红外额温枪方案