今天给你们介绍两个黑魔法,这都是压箱底的法宝。你们在使用时,必定要弄清他们的适用场景及用法,用好了,就是一把开天斧,用很差那就是多此一举。自从看过耗子哥(左耳朵耗子)的博客,都会给对相应专题有兴趣的小伙伴列出几篇拓展文章,我以为这种方式仍是很是不错,因此这篇文章我也会列出几篇扩展的文章,供想更深刻思考的小伙伴查阅。html
可能有人会认为这两个用法会比较冷门,可是在跨系统调用api的过程当中,表的数据量比较大时,sql查询性能太差,会致使接口响应超时,就会对相应的业务产生很是大的影响。系统优化,你们千万不要觉得只是后端的代码优化而已,sql的优化一样也是重点。mysql
可能有小伙伴会问,Covering Indexes究竟是什么神器呢?它又是如何来提高性能的呢?接下来我会用最通俗易懂的语言来进行介绍,毕竟不是每一个程序猿都要像DBA那样深入理解数据库,知道如何用以及如何用好神器才是最关键的。sql
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.....,酣畅淋漓,怎一个爽字了得。就跟排兵布阵同样,打胜仗当然重要,但得想出成本最低效果最好的阵法,定会收获满满的成就感。api
这条sql要如何来进行优化呢?第一反应可能就是说给“column3”加索引(普通索引或惟一索引)啊,没错,这样确实能在很大程度上提高这条sql的性能。mysql优化
咱们来分析下上面sql的执行计划:由于给“column3”建了索引,就会快速根据这个索引查询到符合条件的结果;而后再去这些符合条件的结果里查找所需的column一、column2字段;请注意,整个过程出现了两次查询,一次是查询索引,另外一次查询结果的所需字段。性能
那能不能将上面说的执行计划再优化一下呢?大杀器Covering Indexes就是用来干这事的。给column三、column一、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
接下来给你们下另外一个性能提高神器-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了。
分析到这里,必需要重点说下:
扩展阅读:
https://stackoverflow.com/questions/512294/when-to-use-straight-join-with-mysql