MySQL查询优化

一、简介

     一个好的web应用,最重要的一点是有着优秀的访问性能。数据库MySQL是web应用的组成部分,也是决定其性能的重要部分。因此提高MySQL的性能相当重要。php

     MySQL性能的提高可分为三部分,包括硬件、网络、软件。其中硬件、网络取决于公司的财力,须要白哗哗的银两,这里就不说啦。软件又细分为不少种,在这里咱们经过MySQL的查询优化从而达到性能的提高。html

     最近看了一些关于查询优化的书籍,同时也在网上看一些前辈们写的文章。web

如下是本身整理借鉴关于查询优化的一些总结:算法

二、截取SQL语句

     一、全面查询日志数据库

     二、慢查询日志缓存

     三、二进制日志网络

     四、进程列表并发

  SHOW FULL PROCESSLIST;函数

  。。。性能

三、查询优化基本分析命令

  一、EXPLAIN {PARTITIONS|EXTENDED}

  二、SHOW CREATE TABLE tab;

  三、SHOW INDEXS FROM tab;

  四、SHOW TABLE STATUS LIKE ‘tab’;

  五、SHOW [GLOBAL|SESSION] STATUS LIKE ‘’;

  六、SHOW VARIABLES

  。。。。

  ps:我本身都感受上面都是没任何养分的东西。下面才是真正的干货哈。

四、查询优化几个方向

  一、尽可能避免全文扫描,给相应字段增长索引,应用索引来查询

  二、删除不用或者重复的索引

  三、查询重写,等价转换(谓词、子查询、链接查询)

  四、删除内容重复没必要要的语句,精简语句

  五、整合重复执行的语句

  六、缓存查询结果

五、索引优化

  5.一、索引优势:

    一、保持数据的完整性

    二、提升数据的查询性能

    三、改进表的链接操做(jion)

    四、对查询结果进行排序。没索引将会采用内部文件排序算法进行排序,效率较慢

    五、简化聚合数据操做

  5.二、索引缺点

    一、索引须要占用必定的存储空间

    二、数据插入、更新、删除时会受索引的影响,性能会下降。由于数据变动索引也须要进行更新

    三、多个索引,优化器须要耗时则优选择

  5.三、索引选择

    一、数据量大时采用

    二、数据高度重复时,不采用

    三、查询取出数据大于20%,将采用全文扫描,不用索引

  5.四、索引细究

    资料查询:

    MySQL中的InnoDB、MyISAM都是B-Tree类型索引

    B-Tree包含:PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT

    B-Tree类型索引不支持(即字段使用如下符号时,将不采用索引):

    >, <, >=, <=, BETWEEN, !=, <>,like ‘%**’

    【在此先介绍一下覆盖索引】

    以我本身理解的方式介绍吧。覆盖索引并非像主键索引、惟一索引同样真实存在,它只是对索引应用某些特定场景的一种定义【另外一种理解:查询的列是索引列,所以列被索引覆盖】。它能够突破传统的限制,使用以上操做符,且依然采用索引进行查询。

    由于查询的列是索引列,因此不须要读取行,只须要读取列字段数据就能够了。【例如你看一本书,须要找某一内容,恰好那内容出如今目录中,那就不用一页页翻了,直接在目录中定位到第几页查找】

    如何激活覆盖索引呢?什么样才是特定场景呢?

    索引字段,在select中出现就是了。

    复合索引还可能有其余的特殊场景。例如,三列复合索引,仅须要在select、where、group by、order by中,任意一个地方出现一次复合索引最左边列就能够激活使用覆盖索引了。

    查看:

    EXPLAIN中Extra显示有Using index表示这条语句采用了覆盖索引。

    结论:

    不建议在查询的时候使用select*from进行查询了,应该写须要用的字段,而且增长相应的索引,以提升查询性能。

    针对以上操做符实测结果:

    一、以select*from形式,where中是primary key能够通杀【除like】(使用主键进行查询);index则全不能够。

    二、以select 字段a from tab where 字段a《以上操做符》形式测试,结果依然可使用索引查询。【采用了覆盖索引】

    其余索引优化方法:

    一、使用索引关键字做为链接的条件

    二、复合索引使用

    三、索引合并or and,将涉及到的字段合并成复合索引

    四、where、和group by涉及字段加索引

六、子查询优化

  在from中为非相关子查询,能够上拉子查询到父层。在多表链接查询考虑链接代价再选择。

  查询优化器对子查询通常采用嵌套执行的方式,即对父查询中的每一行,都执行一次子查询,这样子查询会执行不少次。这种执行方式效率很低。

  子查询转化为链接查询优势:

  一、子查询不用执行不少次

  二、优化器能够根据信息来选择不一样的方法和链接顺序

  三、子查询的链接条件,过滤条件变成父查询的筛选条件,以提升效率。

  优化:

  子查询合并,若多个子查询,能合并的尽可能合并。

  子查询展开,即上拉变成多表查询(时刻保证等价变化)

  注意:

  子查询展开只能展开简单的查询,若子查询含有汇集函数、GROUP BY、DISTINCT,则不能上拉。

  select * from t1 (select*from tab where id>10) as t2 where t1.age>10 and t2.age<25;

  select*from t1,tab as t2 where t1.age>10 and t2.age<25 and t2.id>10;

  具体步骤:

  一、from与from合并,修改相应参数

  二、where与where合并,用and链接

  三、修改相应的谓词(in改=)

七、等价谓词重写:

  一、BETWEEEN AND改写为 >= 、<=之类的。实测:十万条数据,重写先后时间,1.45s、0.06s

  二、in转换多个or。字段为索引时,两个都能用到索引,or效率相对in好一点

  三、name like ‘abc%’改写成name>=’abc’ and name<’abd’;

  注意:百万级数据测试,name没有索引以前like比后一种查询快;给字段增长索引后,后面的快一点点,相差不大,由于两种方法在查询的时候都用到了索引。

  。。。。

八、条件化简与优化

  一、将where、having(不存在groupby和汇集函数时)、join-on条件能合并的尽可能合并

  二、删除没必要要的括号,减小语法分许的or和and树层,减小cpu消耗

  三、常量传递。a=b and b=2转换为 a=2 and b=2。尽可能不使用变量a=b或a=@var

  四、消除没用的SQL条件

  五、where等号右边尽可能不出现表达式计算;where中不要对字段进行表达式计算、函数的使用

  六、恒等变换、不等式变换。例:测试百万级数据a>b and b>10变为a>b and a>10 and b>10优化显著

九、外链接优化

  即将外链接转为内链接

  优势:

  一、优化处理器处理外链接比内链接步骤多且耗时

  二、外链接消除后,优化器选择多表链接顺序有更多选择,能够择优而选

  三、能够将筛选条件最为严格的表做为外表(链接顺序最前面,是多层循环体的外循环层),

  能够减小没必要要的I/O开销,能加快算法执行的速度。

  on a.id=b.id与where a.id=b.id的差异,on则表进行链接,where则进行数据对比

  注意:前提必须是结果为NULL决绝(即条件限制不要NULL数据行,语意上是内链接)

  优化原则:

  精简查询,链接消除,等效转换,去除多余表对象链接

  例如:主键/惟一键做为链接条件,且中间表列只做为等值条件,能够去掉中间表链接

十、其余查询优化

  一、如下将会形成放弃索引查询,采用全文扫描

    1.一、where 子句中使用!=或<>操做符  注意:主键支持。非主键不支持

    1.二、避免使用or

      经测试,并不是是使用了or就必定不能使用索引,大多状况下是没用到索引,但还有少数状况是用到的,所以具体状况具体分析。

      相似优化:

      select * from tab name=’aa’ or name=’bb’;

      =>

      select * from tab name=’aa’

      union all

      select * from tab name=’bb’;

      实测:

      一、十万数据测试,没任何索引的状况下,上面比下面的查询速率快一倍。

      二、三十万数据测试,aa与bb都是单独索引状况下,下面的查询速率比or快一点。

    1.三、避免使用not in

      not in通常不能使用索引;主键字段能够

    1.四、where中尽可能避免使用对null的判断

    1.五、like不能前置百分号 like ‘%.com’

      解决:

        一、若必须使用%前置,且数据长度不大,例如URL,可将数据翻转存入数据库,再来查。LIKE REVERSE‘%.com’;

        二、使用覆盖索引

 

    1.六、使用索引字段做为条件的时候,倘若是复合索引,则应该使用索引最左边前缀的字段名

  二、将exists代替in

    select num from a where num in(select num from b)

    select num from a where exists(select 1 from b where num=a.num)

    一百万条数据,筛选59417条数据用时6.65s、4.18s。没作其余优化,仅仅只是将exists替换in。

  三、字段定义是字符串,查询时没带引号,不会用索引,将会进行全文扫描。

  【如下是摘抄于半夜乱弹琴博文http://www.cnblogs.com/lingiu/p/3414134.html,本人没进行相应的测试】

  四、尽可能使用表变量来代替临时表

  五、避免频繁建立和删除临时表,以减小系统表资源的消耗

  六、若是使用到了临时表,在存储过程的最后务必将全部的临时表显式删除,先 truncate table ,而后 drop table ,这样能够避免系统表的较长时间锁定

  七、尽可能避免使用游标,由于游标的效率较差,若是游标操做的数据超过1万行,那么就应该考虑改写

  八、大数据量,若数据量过大,应该考虑相应需求是否合理。

  九、尽可能避免大事务操做,提升系统并发能力。

  。。。。。

十一、博文总结

  通过这些天查资料敲代码的学习,了解到了MySQL的查询优化并非简简单单的按照某个公式某个规则就可达到的。实验是检验标准的惟一标准,通过这几天的测试,得出的结论就是:MySQL的查询优化是有大方向,可是想要得出一个万能优化公式那是不可能的,毕竟每一条SQL查询语句的写法、结果着重点、以及表的字段环境都不同。可以达到看SQL查询语句就能得出优化方法的大神,一定是仔细研究过SQL查询优化而且有过好几年优化经验的老鸟。哈哈,我还只是个小菜鸟。

  建议各位正在学习SQL查询优化的童鞋们:不要仅仅只是看,要多敲代码,多测试,各类字段环境测试、各类数据量级别测试。

 

以上是本身的一些总结,也许有些不足。毕竟本身还只是个菜鸟,而且也不是DBA的方向,若你们发现有不足的地方,或者错误的地方,请您可以提出来。

 

做者:那一叶随风

声明:转载时请在文章页面明显位置给出原文连接。

相关文章
相关标签/搜索