首页 > 数据库 >MySQL联表查询优化

MySQL联表查询优化

时间:2023-09-04 14:45:25浏览次数:42  
标签:查询 索引 JOB 联表 MySQL where id select

Linux系统-部署-运维系列导航

 


 

sql执行顺序

  1. 执行FROM语句
  2. 执行ON过滤
  3. join添加外部行
  4. 执行where条件过滤
  5. 执行group by以及分组语句,(开始使用select中的别名,后面的语句中都可以使用别名)
  6. 执行having
  7. select列表
  8. 执行distinct去重复数据
  9. 执行order by字句
  10. 执行limit字句

 


多表联合查询优化建议

 

1、使用显示连接left join(right join,inner join),尽量避免隐式连接(where逗号连接表 .... and .... and ...)这类写法,假设三张表每张表有一千条数据,本意想查出<=1000条数据,当使用where语句查询,就查出了1000*1000*1000=10亿条数据,很大程度上浪费了内存执行时间  ps:在不使用on语法时,join、inner join、逗号、cross join结果相同,都是取2个表的笛卡尔积。逗号与其他操作符优先级不同,所以有可能产生语法错误,尽量减少用逗号   2、需要哪些列就查哪些列,不要有很多冗余的列查询出来,有的时候一张表当中有好几十个字段,我们需要的可能就是其中的三四个或者四五个字段,在这样的情况下,我们就直接查这几个我们需要的字段就可以了   3、尽量避免使用  .*  ,因为使用点* 需要先去数据字典当中查找你所查找的表当中所拥有的字段,再转换成对应的字段的放在select后面查询出来   4、优先使用大于等于,比大于执行效率高   5、查询的时候我们应该把更具有限制条件的条件语句放在最前面,比如我们有一张学生成绩表(score),分别有学号、语数英三科成绩以及总成绩总共五列,要查找数学、英语优秀,语文及格,总成绩再前一百名的人 
select * from score where sno in(select sno from score where language>60 and math>80 and english>80 order by total_score desc)(慢) 
select sno,language,math,english,total_score from score where exist (select sno from where engilsh>=80 and math>=80 and language>=80 order by total_score desc)(快) 
上面那条语句将大于60分的条件放前面,大于80的放后面,导致很多情况下多查了很多数据  就比如说一张表里有有很多字段,有一百万条记录,主键id由1到1百万,当我们需要查找小于1000大于100的数据的时候,我们就应该把小于1000这个条件放前面,这就是相对比下最具限制性的条件   6、尽量使用连接查询 替代 子查询,因为子查询需要建立/销毁临时表,开销昂贵
select a.id,a.name from a where a.id in(select b.aid from b where b.id=123);
select a.id,a.name from a inner join b on a.id=b.aid wehre b.id=123; 
子查询执行表现为,外表遍历每一条,内表都需要扫描一次,边遍历查询外表,边扫描内表; 如果数量较大,则使用连接查询,因为子查询会扫描多次; 如果数据量较小,则子查询与连接查询对比不明显 如果需要用到子查询: 6.1、用EXISTS(或内连接)替代IN、用NOT EXISTS(或者外连接)替代NOT IN 6.2、用EXISTS替换DISTINCT   7、where条件尽量使用索引,避免在索引列使用计算(加减乘除),避免索引列使用函数(转换类型),避免索引列使用is(not)null,避免索引列使用通配符,否则数据库将放弃索引,执行全表扫描   8、where代替having,优化group by 提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉,如下 低效: SELECT JOB , AVG(SAL) FROM EMP GROUP BY JOB HAVING JOB = ‘PRESIDENT' OR JOB = ‘MANAGER' 高效: SELECT JOB , AVG(SAL) FROM EMP WHERE JOB = ‘PRESIDENT' OR JOB = ‘MANAGER' GROUP BY JOB   9、Order By语句加在索引列,最好是主键PK上   10、用EXISTS替换DISTINCT  当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果   11、in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in(减少遍历次数)   12、字符串型=,in,like’abc%‘索引生效;!=, not in, like'%abc', like'a%bc'索引失效   13、数值型=, !=, in, not in都可以索引生效  

索引一般性建议

  • 对于单键索引,尽量选择针对当前query过滤性更好的索引
  • 在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好
  • 在选择组合索引的时候,尽量选择可以能够包含当前query中的where子句中更多字段的索引
  • 尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的
 

索引口诀

  • 全职匹配我最爱,最左前缀要遵守
  • 带头大哥不能死,中间兄弟不能断
  • 索引列上少计算,范围之后全失效
  • like百分写最右,覆盖索引不写星
  • 不等空值还有or,索引失效要少用
  • var引号不可丢,SQL高级也不难
 

参考资料

https://blog.csdn.net/include_ice/article/details/81323535 https://blog.csdn.net/huanghanqian/article/details/52847835 https://blog.csdn.net/di_yun_hah/article/details/78968119 https://blog.csdn.net/insis_mo/article/details/82897665 https://blog.csdn.net/weixin_34294809/article/details/113301058 https://blog.csdn.net/zsx157326/article/details/79406491

标签:查询,索引,JOB,联表,MySQL,where,id,select
From: https://www.cnblogs.com/xiaoyaozhe/p/17671333.html

相关文章

  • MybatisPlus处理Mysql的json类型
    MybatisPlus处理Mysql的json类型1、在数据库表定义JSON字段;2、在实体类加上@TableName(autoResultMap=true)、在JSON字段映射的属性加上@TableField(typeHandler=JacksonTypeHandler.class);1.实体类中有个属性是其他对象,或者是List;在数据库中存储时使用的是mysql的json格式,此......
  • mysql到达梦存储过程常见问题
    1.1 变量的使用createorreplaceproceduree_test()asbegin setstrsql='selectidinto@eidfromtest2orderbyidlimit1,10'; insertintotestselectid,namefromtest2whereidin(eid); setstst=strsql; executestst;end;变量需要提前定义cre......
  • MySQL忘记root密码解决方案
    Linux系统-部署-运维系列导航 场景一:重置root密码mysql登录密码为password()算法加密,解密成本太高,以下为通用方案;原理:mysql提供了特殊启动方式,即跳过权限表验证,启动后,登录不需要提供密码;登录后,即可修改mysql数据库的user表,重置密码,然后刷新权限,重启mysql服务即可;注意:此时my......
  • docker桌面端安装mysql
    参考 https://www.yzktw.com.cn/post/735256.html1,搜索Images,mysql,选择合适的版本pull2,Images,中点击三角箭头,run,会弹出新建Containers弹框Containersname,随便写Ports需要写0Volumes选安装地址EnvironmentVarialbes需要加上密码MYSQL_ROOT_PASSWORD: 123456 3,运行......
  • keepalived实现MySQL MGR高可用(keepalived 2.2.7 + mysql 5.7.35)
    Linux系统-部署-运维系列导航 一、架构介绍MySQLMGR实现了MySQL服务的高可用、高扩展、高可靠,但在客户端只能同时连接一台服务实例,在master切换后,客户端无法感知并自动切换,所以需要搭配keepalived实现MySQLMGR集群在客户端的高可用。 二、架构搭建架构设计MySQLMGR一......
  • Linux 服务器下C++开发找不到mysql.h
    问题背景腾讯云服务器,linuxcentOS7内核,mysql版本5.5为宝塔腾讯云版自动安装C++用cmake编译时找不到mysql.h解决1.首先尝试yum安装mysql-devel包,但是yum让我直接下载了mariadb相关的包,下载时它,与原有包冲突bt-mysql55-5.5.62-1.el7.x86_64,但是删除原有包后mysql启动有问......
  • 浅谈Mysql读写分离的坑以及应对的方案 | 京东云技术团队
    一、主从架构为什么我们要进行读写分离?个人觉得还是业务发展到一定的规模,驱动技术架构的改革,读写分离可以减轻单台服务器的压力,将读请求和写请求分流到不同的服务器,分摊单台服务的负载,提高可用性,提高读请求的性能。上面这个图是一个基础的Mysql的主从架构,1主1备3从。这种架构是客户......
  • 将MySQL分区表转换成普通表
    将MySQL分区表转换成普通表MySQL支持分区表,这种表可以将数据分散到多个存储区中。但是,有时候我们可能需要把分区表转换成普通表,本文将介绍如何完成这个操作。备份数据在进行任何表修改操作前,都需要先进行数据备份。在备份数据之前,需要关闭所有对该表的写入操作。取消分区要将分区表......
  • mysql中文全文搜索
    在MySQL5.7.6之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分词器把中文段落预处理拆分成单词,然后存入数据库。从MySQL5.7.6开始,MySQL内置了ngram全文解析器,用来支持中文、日文、韩文分词。本文使用的MySQL版本是5.7.22,InnoDB数据库引擎。为什么要用全文索引呢?......
  • 浅谈Mysql读写分离的坑以及应对的方案
    一、主从架构为什么我们要进行读写分离?个人觉得还是业务发展到一定的规模,驱动技术架构的改革,读写分离可以减轻单台服务器的压力,将读请求和写请求分流到不同的服务器,分摊单台服务的负载,提高可用性,提高读请求的性能。上面这个图是一个基础的Mysql的主从架构,1主1备3从。这种架构是......