【黑魔法】Covering Indexes、STRAIGHT_JOIN
今天给大家介绍两个黑魔法,这都是压箱底的法宝。大家在使用时,一定要弄清他们的适用场景及用法,用好了,就是一把开天斧,用不好那就是画蛇添足。自从看过耗子哥(左耳朵耗子)的博客,都会给对相应专题有兴趣的小伙伴列出几篇拓展文章,我觉得这种方式还是非常不错,所以这篇文章我也会列出几篇扩展的文章,供想更深入思考的小伙伴查阅。
可能有人会认为这两个用法会比较冷门,但是在跨系统调用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://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://dev.mysql.com/doc/refman/8.0/en/join.html
【黑魔法】Covering Indexes、STRAIGHT_JOIN的更多相关文章
- 【性能提升神器】Covering Indexes
可能有小伙伴会问,Covering Indexes到底是什么神器呢?它又是如何来提升性能的呢?接下来我会用最通俗易懂的语言来进行介绍,毕竟不是每个程序猿都要像DBA那样深刻理解数据库,知道如何用以及如 ...
- Covering Indexes in MySQL, PostgreSQL, and MongoDB
Covering Indexes in MySQL, PostgreSQL, and MongoDB - Orange Matter https://orangematter.solarwinds.c ...
- Index-Only Scans and Covering Indexes
小结: 1.覆盖索引 回表 2. All indexes in PostgreSQL are secondary indexes, meaning that each index is stored ...
- 高性能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 ...
- PostgreSQL 11 新特性之覆盖索引(Covering Index)(转载)
通常来说,索引可以用于提高查询的速度.通过索引,可以快速访问表中的指定数据,避免了表上的扫描.有时候,索引不仅仅能够用于定位表中的数据.某些查询可能只需要访问索引的数据,就能够获取所需要的结果,而不需 ...
- MySQL: Building the best INDEX for a given SELECT
Table of Contents The ProblemAlgorithmDigressionFirst, some examplesAlgorithm, Step 1 (WHERE "c ...
- 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 ...
- SQL SERVER中什么情况会导致索引查找变成索引扫描
SQL Server 中什么情况会导致其执行计划从索引查找(Index Seek)变成索引扫描(Index Scan)呢? 下面从几个方面结合上下文具体场景做了下测试.总结.归纳. 1:隐式转换会导致 ...
- (转)理解MySQL——索引与优化
参考资料:http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html ———————————— 全文: 写在前面:索引对查询的速度有着 ...
随机推荐
- angularjs 中通过 $location 进行路由跳转传参
$location.path('/page1').search({id: $scope.id,name:$scope.name}); 带参数跳转页面,在新的页面通过$routeParams接收参数 $ ...
- zabbix分布式监控的部署与win被控端
zabbix是一个分布式监视,管理系统,基于server-clinet架构,可用于监视各种网络服务,服务器和网络机器等状态. server端基于C语言,web管理端Frontend则是基于PHPA制作 ...
- sendfile
Sendfile 函数在两个文件描写叙述符之间直接传递数据(全然在内核中操作,传送),从而避免了内核缓冲区数据和用户缓冲区数据之间的拷贝,操作效率非常高,被称之为零拷贝. Sendfile 函数的定义 ...
- 12px以下字体显示问题
刚接到广告公司出的设计稿,里面很多内容均是12px以下得字体,现在来总结一下解决办法,方便以后使用 1.使用png图片 但是会影响页面响应速度 2.使用transform: scale(0.x); 注 ...
- Python知识回顾 —— 面向对象
博客转载自 http://www.cnblogs.com/wupeiqi/p/4766801.html http://www.cnblogs.com/linhaifeng/articles/62040 ...
- Codeforces Round #517 体验记
原文链接 https://www.cnblogs.com/zhouzhendong/p/CF1071.html 赛前: 呀,这个 Round # 必须打啊. 于是临时改变注意决定打这一场.用小号打. ...
- 51nod1967 路径定向 Fleury
题目传送门 题解 几乎是Fleury模板题. 一开始我们把图看作无向图,然后对于度为奇数的点增边,使得整个图的所有点都是偶数的. 然后跑一遍欧拉回路 Fleury ,所有的边就定向好了~ 代码 #in ...
- request和session的区别
request多用于表单提交,表单数据等 session用于服务器端的记录变量,比如用户的登陆和登出啊 request 资源占用小,安全性较高,但是不持续性 session 资源消耗较大,安全性较低, ...
- QT5版本添加icon图标步骤
QT5版本添加icon图标方法收藏 方法1: step1: 把要显示的图标文件,比如为1.ico文件放到工程v的根目录下 step2: 修改当前项目XXX.pro文件,在文件末尾添加如下内容(注意=的 ...
- 附001.kubectl介绍及使用
一 kubectl介绍 1.1 kubectl概要 kubectl控制Kubernetes集群管理器,使用Kubernetes命令行工具kubectl在Kubernetes上部署和管理应用程序.使用k ...