今天给大家介绍两个黑魔法,这都是压箱底的法宝。大家在使用时,一定要弄清他们的适用场景及用法,用好了,就是一把开天斧,用不好那就是画蛇添足。自从看过耗子哥(左耳朵耗子)的博客,都会给对相应专题有兴趣的小伙伴列出几篇拓展文章,我觉得这种方式还是非常不错,所以这篇文章我也会列出几篇扩展的文章,供想更深入思考的小伙伴查阅。

可能有人会认为这两个用法会比较冷门,但是在跨系统调用api的过程中,表的数据量比较大时,sql查询性能太差,会导致接口响应超时,就会对相应的业务产生非常大的影响。系统优化,大家千万不要以为只是后端的代码优化而已,sql的优化同样也是重点

1.Covering Indexes

可能有小伙伴会问,Covering Indexes到底是什么神器呢?它又是如何来提升性能的呢?接下来我会用最通俗易懂的语言来进行介绍,毕竟不是每个程序猿都要像DBA那样深刻理解数据库,知道如何用以及如何用好神器才是最关键的。

Covering Indexes就是一个索引覆盖所有要查询的字段(ps:这句话我挖个坑,文末我来解释)。

An index that contains all required information to resolve the query is known as a “Covering Index” – it completely covers the query.
Covering Index includes all the columns, the query refers to in the SELECT, JOIN, and WHERE clauses.

接下来我们通过一个非常简单的sql来进行分析:

SELECT column1, column2 FROM tablename WHERE column3=xxx;

你能想象将sql的执行时间从1.8秒,降到1.2秒,继续压榨到0.5,0.2.....,酣畅淋漓,怎一个爽字了得。就跟排兵布阵一样,打胜仗固然重要,但得想出成本最低效果最好的阵法,定会收获满满的成就感。

这条sql要如何来进行优化呢?第一反应可能就是说给“column3”加索引(普通索引或唯一索引)啊,没错,这样确实能在很大程度上提升这条sql的性能。

我们来分析下上面sql的执行计划:因为给“column3”建了索引,就会快速根据这个索引查询到符合条件的结果;然后再去这些符合条件的结果里查找所需的column1、column2字段;请注意,整个过程出现了两次查询,一次是查询索引,另一次查询结果的所需字段。

那能不能将上面说的执行计划再优化一下呢?大杀器Covering Indexes就是用来干这事的。给column3、column1、column2建个复合索引,如下:

alter table table_name add index index_column3 (column3,column1,column2) ;

这样就可以直接通过索引就能查询出符合条件的数据,而不必像上面那样先去查索引,然后再去查数据的两个过程

光说不练那是假把式!小伙伴们可以用explain去试试上面的两种情况,如果执行复合索引后的情况,你会发现Extra里出现Using index。

刚开始我说挖了个坑,现在我把坑填上。既然神器Covering Indexes这么好用,以后select语句的我都不管三七二十一的都亮出神器。难不成你select *也要亮神器?一个表那么多字段,全建成索引?那索引文件会不堪重负的,这就会适得其反,带来一系列恶果的。索引文件过大会造成insert、update非常慢,你select倒是爽快了,不能不顾其他兄弟吧,不仗义的事咱不能干,切记!

如果看完这个分析还不过瘾,下面我给几篇扩展文章:

https://www.c-sharpcorner.com/UploadFile/b075e6/improving-sql-performance-using-covering-indexes/

https://www.red-gate.com/simple-talk/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/

https://stackoverflow.com/questions/609343/what-are-covering-indexes-and-covered-queries-in-sql-server

https://stackoverflow.com/questions/62137/what-is-a-covered-index

2.STRAIGHT_JOIN

接下来给大家下另一个性能提升神器-STRAIGHT_JOIN,在数据量大的联表查询中灵活运用的话,能大大缩短查询时间。

首先来解释下STRAIGHT_JOIN到底是用做什么的:

STRAIGHT_JOIN is similar to JOIN, except that the left table is always read before the right table.
This can be used for those (few) cases for which the join optimizer puts the tables in the wrong order.

意思就是说STRAIGHT_JOIN功能同join类似,但能让左边的表来驱动右边的表,能改表优化器对于联表查询的执行顺序。

接下来我们举个例子进行大致的分析:

select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1

以上sql大数据量下执行需要30s,是不是很奇怪?明明Table1表的FilterID字段建了索引啊,Table1和Table2的CommonID也建了索引啊。通过explain来分析,你会发现执行计划中表的执行顺序是Table2->Table1。这个时候要略微介绍下驱动表的概念,mysql中指定了连接条件时,满足查询条件的记录行数少的表为驱动表;如未指定查询条件,则扫描行数少的为驱动表。mysql优化器就是这么粗暴以小表驱动大表的方式来决定执行顺序的

但如下sql的执行时间都少于1s:

select t1.*
from Table1 t1
where t1.FilterID = 1

select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID

这个时候STRAIGHT_JOIN就派上用场,我们对sql进行改造如下:

select t1.*
from Table1 t1
STRAIGHT_JOIN Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1

用explain进行分析,发现执行顺序为Table1->Table2,这时就由Table1来作为驱动表了,Table1中相应的索引也就用上了,执行时间竟然低于1s了。

分析到这里,必须要重点说下:

  • STRAIGHT_JOIN只适用于inner join,并不使用与left join,right join。(因为left join,right join已经代表指定了表的执行顺序)
  • 尽可能让优化器去判断,因为大部分情况下mysql优化器是比人要聪明的。使用STRAIGHT_JOIN一定要慎重,因为啊部分情况下认为指定的执行顺序并不一定会比优化引擎要靠谱。

扩展阅读:

https://stackoverflow.com/questions/512294/when-to-use-straight-join-with-mysql

https://stackoverflow.com/questions/5818837/why-does-straight-join-so-drastically-improve-this-query-and-what-does-it-mean

https://dev.mysql.com/doc/refman/8.0/en/join.html

【黑魔法】Covering Indexes、STRAIGHT_JOIN的更多相关文章

  1. 【性能提升神器】Covering Indexes

    可能有小伙伴会问,Covering Indexes到底是什么神器呢?它又是如何来提升性能的呢?接下来我会用最通俗易懂的语言来进行介绍,毕竟不是每个程序猿都要像DBA那样深刻理解数据库,知道如何用以及如 ...

  2. Covering Indexes in MySQL, PostgreSQL, and MongoDB

    Covering Indexes in MySQL, PostgreSQL, and MongoDB - Orange Matter https://orangematter.solarwinds.c ...

  3. Index-Only Scans and Covering Indexes

    小结: 1.覆盖索引 回表 2. All indexes in PostgreSQL are secondary indexes, meaning that each index is stored ...

  4. 高性能MySQL笔记-第5章Indexing for High Performance-001B-Tree indexes(B+Tree)

    一. 1.什么是B-Tree indexes? The general idea of a B-Tree is that all the values are stored in order, and ...

  5. PostgreSQL 11 新特性之覆盖索引(Covering Index)(转载)

    通常来说,索引可以用于提高查询的速度.通过索引,可以快速访问表中的指定数据,避免了表上的扫描.有时候,索引不仅仅能够用于定位表中的数据.某些查询可能只需要访问索引的数据,就能够获取所需要的结果,而不需 ...

  6. MySQL: Building the best INDEX for a given SELECT

    Table of Contents The ProblemAlgorithmDigressionFirst, some examplesAlgorithm, Step 1 (WHERE "c ...

  7. Differences between INDEX, PRIMARY, UNIQUE, FULLTEXT in MySQL?

    487down vote Differences KEY or INDEX refers to a normal non-unique index.  Non-distinct values for ...

  8. SQL SERVER中什么情况会导致索引查找变成索引扫描

    SQL Server 中什么情况会导致其执行计划从索引查找(Index Seek)变成索引扫描(Index Scan)呢? 下面从几个方面结合上下文具体场景做了下测试.总结.归纳. 1:隐式转换会导致 ...

  9. (转)理解MySQL——索引与优化

    参考资料:http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html ———————————— 全文: 写在前面:索引对查询的速度有着 ...

随机推荐

  1. Android SDK离线安装更新方法

    直接使用Android SDK Manager进行下载.更新速度很慢,有时候会出现错误.网上查找了不少网友的方法,做个总结. 1.启动Android SDK Manager,并等待reposity加载 ...

  2. ionic2集成sdk后,连接超时的问题

    这几天在测试app的时候,偶尔会发现集成的好视通sdk在进入会议室的时候出现连接超时的问题,一直卡在‘正在获取版本信息’的页面,经反复测试后这种现象主要出现在点击返回按钮和退出登录按钮的时候会出现,也 ...

  3. Javascript 中调参数的脚本onclick="select(this)" this 怎么解释

    解释1. this,指当前的onclick所在的节点本身. 比如: <div onclick='select(this)"></div> 则当点击div时,this就 ...

  4. yii的ActionForm组件

    //文本框:textInput(); //密码框:passwordInput(); //单选框:radio(),radioList(); //复选框:checkbox(),checkboxList() ...

  5. 【转】科大校长给数学系学弟学妹的忠告&本科数学参考书

    1.老老实实把课本上的题目做完.其实说科大的课本难,我以为这话不完整.科大的教材,就数学系而言还是讲得挺清楚的,难的是后面的习题.事实上做1道难题的收获是做10道简单题所不能比的. 2.每门数学必修课 ...

  6. ibatis的queyrForList和queryForMap区别

    https://blog.csdn.net/z69183787/article/details/47360825 https://blog.csdn.net/zyq527758142/article/ ...

  7. SSM知识点与整合之Spring知识点(pom.xml需要依赖的jar或者plugin)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  8. [dotnet core]使用Peach简化Socket网络通讯协议开发

    Peach是基于DotNetty的Socket网络通讯帮助类库,可以帮助开发者简化使用DotNetty,关于DotNetty可参考我之前的这篇文章. Peach内置实现了一个基于文本协议的Comman ...

  9. linux 学习笔记 wc命令

    #wc 文件名.txt 输出 4 13 65 文件名.txt  -->4 行13个单词 #wc -w 文件名.txt  统计单词数量 #wc -l 文件名.txt  统计行数 #wc -c  文 ...

  10. SpringBoot使用缓存

    前言 我们都知道,一个程序的瓶颈通常都在数据库,很多场景需要获取相同的数据.比如网站页面数据等,需要一次次的请求数据库,导致大部分时间都浪费在数据库查询和方法调用上,这时就可以利用到缓存来缓解这个问题 ...