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个表的笛卡尔积。逗号与其他操作符优先级不同,所以有可能产生语法错误,尽量减少用逗号
 
特别关注:关于join语句中 on,and,where的区别,以left join为例,参考验证示例
1、on关键字是对left join的右表进行条件过滤,但是依旧会返回左表的所有内容,右表不满足on条件都置为null。

2、and关键字,不管是左表还是右表的条件,左表的内容依旧不变,不符合and筛选条件的右表置为null。

3、where关键字,不管左表还是右表,只要不满足where筛选条件的两个表都会过滤掉。

 

 
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 score 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高级也不难
 

参考资料

posted on 2023-09-04 14:29  xiaoyaozhe  阅读(665)  评论(0编辑  收藏  举报