《深入浅出MySQL》读书笔记五:SQL优化

一、SQL优化的一般步骤

show status like 'pattern%';  查看数据库的运行时状态
show variables like 'pattern%';  查看数据库启动时的配置信息

1、首先需要定位执行效率有问题的SQL:

    a、执行效率有问题的SQL一般都耗时较长,业务是有感知的,从而可以帮助定位

    b、在MySQL启动时,设置 slow_query_log 打开慢查询日志   long_query_time 设置慢查询时间阈值,这样可以通过慢查询日志定位效率有问题的SQL。

2、通过 explain 分析sql的执行计划,对于慢查询sql主要看  possible keys 和 key ,分析索引的使用情况。

      key为null的情况,则 sql没有走索引。

      可能原因:1)、没有索引,需要创建 2)、存在索引,但是mysql选择不走索引

      使用索引的可能情况:a、多列索引,查询条件使用了 索引中最左边的列

                                          b、like 'pattern%' 的情况   %在后面

                                          c、大文本进行搜索,建立 全文索引, 而不是 like '%pattern%'

                                          d、如果为列 name建立索引,则  where name is null 将使用索引 

扫描二维码关注公众号,回复: 4815120 查看本文章

       存在索引但是不适用索引的情况:

                                          a、范围查询表中大部分数据时,MySQL判断全表扫描比索引更加合适的情况下,不会使用索引

                                          b、使用  or分隔开的条件,当所有的条件列都 创建了 索引时,才会使用索引

                                          c、列类型是 字符串类型,查询时 不加 引号 就 不会使用索引(虽然会进行类型的转换),列类型是 整数类                                                     型,查询时 加了 引号,也会走索引

二、优化的常见方法

1、表优化   

      对  MyISAM和InnoDB类型的表来说,可以定期  分析表,检查表,优化表

analyze table b; 分析表 使得系统得到准确的统计信息,是的SQL能够生成正确的执行计划
check table b;   检查表 查看是否存在错误
optimize table b;  优化表,当表中存在动态类型(varchar text blob)时,对这些字段频番的更新和删除会造成大量的空间碎片,优化表可以对表空间碎片进行整理,减少空间的浪费

2、SQL优化

     a、优化 INSERT:同一客户插入多条数据时,将所有的数据 组装为一条SQL语句提交;不同客户端插入多行,可以使用 insert delayed 语句,在对数据实时性要求不高的情况下可以使用,很快的原因在于数据并没有真正插入文件,而是保存在内存的队列中等待插入;可以配置数据库,或者在建表时指定 数据目录和索引目录存放到不同的磁盘上,平均分布磁盘IO,性能会有所提高;当从一个文本文件装载一个表时,使用 load data infile 通常比 使用很多的 insert语句快很多

     b、优化GROUP BY:默认情况下,MySQL对所有 group by d1,d2 中的 字段进行排序,类似于 加上 order by d1,d2

explain select d2, count(d2) from b group by d2;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: b
   partitions: NULL
         type: index
possible_keys: d1
          key: d1
      key_len: 9
          ref: NULL
         rows: 7
     filtered: 100.00
        Extra: Using index; Using temporary; Using filesort
1 row in set, 1 warning (0.00 sec)

其中 Extra中的 Using filesort 即 进行了排序操作

           排序操作会带来额外的开销,如果 group by 的结果 对排序没有要求,可以加上 order by null 显示指定 不排序

     c、优化 order by 语句:某些情况下,MySQL可以使用一个索引来满足 order by子句,而不需要额外的排序。order by使用索引的条件:where条件和 order by 使用相同的索引,并且 order by顺序和 索引顺序相同,并且order by 的字段都是 升序或者降序

举个栗子:

使用索引:
SELECT * FROM t1 ORDER BY key_part1,key_part2,... ;
SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC; 
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC;
不适用索引:
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;  --order by 的字段混合 ASC 和 DESC SELECT * FROM t1 WHERE key2=constant ORDER BY key1;  --用于查询行的关键字与 ORDER BY 中所使用的不相同 
SELECT * FROM t1 ORDER BY key1, key2;  --对不同的关键字使用 ORDER BY

     d、优化嵌套查询:有些情况下,可以使用 连接操作代替 嵌套查询,连接(JOIN)更有效率的原因在于,MySQL不需要在内存中创建临时表

     e、优化OR条件:为 or 的所有条件列都 建立索引,where a = 2 or  b = 2 当 a、b都有各自的独立索引时,查询可以使用索引,而当 a、b只有组合索引时,查询不会走 索引。

     f、使用SQL提示:use index、ignore index、force index 来强制 使用、忽略相关索引。

3、数据库对象的优化

     a、根据实际情况,或者在 使用一段时间之后,根据统计结果,选择或修改字段的类型 为 更加合适的类型和长度

     b、MyISAM类型的表,可以进行拆分提高表的访问效率

           水平拆分:各个表的结构完全一样,但是 存储的数据 类别不同,按照某个字段分类(地区,月份)。适用于 数据量很大,增长很快,并且数据可以进行分类的场合。优点在于:分割后,降低了查询时需要读的数据和索引的页数,降低索引的层数,提高了查询速度。缺点在于:增加了复杂度,查询所有的数据需要 UNION操作;在索引关键字不大、数据增长速度不那么快的情况下,水平拆分的查询速度和 不拆分的情况下走索引的查询速度相比,可能不会有显著的提高,从而 水分拆分带来的复杂度 成为了 很大的问题。

           垂直拆分:将 主键和一些列放在一个表中,主键和另外一些列放在另一个表中。可以将常用列和不常用的列分开,拆分之后,数据行变小,一个数据页可以存放更多的数据,在查询时就会减少I/O次数。  缺点在于 冗余列的管理,查询所有的数据需要 JOIN操作。

      c、逆规范化-冗余列:在表中增加必要的冗余列,从而降低查询时 连接的需求。问题在于:冗余列的更新,可以考虑 建立触发器,来统一更新冗余列。

      d、统计查询的情况下,可以使用中间表提高查询的速度。例如,统计用户的月账单,可以先将 当月的数据使用  insert into ...select * from... 导入到创建的中间表中,然后在 中间表中进行统计操作。 优点:速度更快,而且可以按需建立索引和增加字段来辅助统计操作。

猜你喜欢

转载自blog.csdn.net/weixin_37882382/article/details/83143204