您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    我必须得告诉大家的MySQL优化原理(6)
    时间:2017-05-03 13:47 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    select user.* from user where login_time > '2017-04-01' and age between 18 and 30; 

    这个查询有一个问题:它有两个范围条件,login_time列和age列,MySQL可以使用login_time列的索引或者age列的索引,但无法同时使用它们。

    5、覆盖索引

    如果一个索引包含或者说覆盖所有需要查询的字段的值,那么就没有必要再回表查询,这就称为覆盖索引。覆盖索引是非常有用的工具,可以极大的提高性能,因为查询只需要扫描索引会带来许多好处:

    索引条目远小于数据行大小,如果只读取索引,极大减少数据访问量

    索引是有按照列值顺序存储的,对于I/O密集型的范围查询要比随机从磁盘读取每一行数据的IO要少的多

    6、使用索引扫描来排序

    MySQL有两种方式可以生产有序的结果集,其一是对结果集进行排序的操作,其二是按照索引顺序扫描得出的结果自然是有序的。如果explain的结果中 type 列的值为 index 表示使用了索引扫描来做排序。

    扫描索引本身很快,因为只需要从一条索引记录移动到相邻的下一条记录。但如果索引本身不能覆盖所有需要查询的列,那么就不得不每扫描一条索引记录就回表查询一次对应的行。这个读取操作基本上是随机I/O,因此按照索引顺序读取数据的速度通常要比顺序地全表扫描要慢。

    在设计索引时,如果一个索引既能够满足排序,有满足查询,是最好的。

    只有当索引的列顺序和 ORDER BY 子句的顺序完全一致,并且所有列的排序方向也一样时,才能够使用索引来对结果做排序。如果查询需要关联多张表,则只有 ORDER BY 子句引用的字段全部为第一张表时,才能使用索引做排序。 ORDER BY 子句和查询的限制是一样的,都要满足最左前缀的要求(有一种情况例外,就是最左的列被指定为常数,下面是一个简单的示例),其他情况下都需要执行排序操作,而无法利用索引排序。

    // 最左列为常数,索引:(date,staff_id,customer_id)  

    select staff_id,customer_id from demo where date = '2015-06-01' order by staff_id,customer_id 

    7、冗余和重复索引

    冗余索引是指在相同的列上按照相同的顺序创建的相同类型的索引,应当尽量避免这种索引,发现后立即删除。比如有一个索引 (A,B) ,再创建索引 (A) 就是冗余索引。冗余索引经常发生在为表添加新索引时,比如有人新建了索引 (A,B) ,但这个索引不是扩展已有的索引 (A) 。

    大多数情况下都应该尽量扩展已有的索引而不是创建新索引。但有极少情况下出现性能方面的考虑需要冗余索引,比如扩展已有索引而导致其变得过大,从而影响到其他使用该索引的查询。

    8、删除长期未使用的索引

    定期删除一些长时间未使用过的索引是一个非常好的习惯。

    关于索引这个话题打算就此打住,最后要说一句,索引并不总是最好的工具,只有当索引帮助提高查询速度带来的好处大于其带来的额外工作时,索引才是有效的。对于非常小的表,简单的全表扫描更高效。对于中到大型的表,索引就非常有效。对于超大型的表,建立和维护索引的代价随之增长,这时候其他技术也许更有效,比如分区表。最后的最后, explain 后再提测是一种美德 。

    特定类型查询优化

    优化COUNT()查询

    COUNT() 可能是被大家误解最多的函数了,它有两种不同的作用,其一是统计某个列值的数量,其二是统计行数。统计列值时,要求列值是非空的,它不会统计NULL。如果确认括号中的表达式不可能为空时,实际上就是在统计行数。最简单的就是当使用 COUNT(*) 时,并不是我们所想象的那样扩展成所有的列,实际上,它会忽略所有的列而直接统计所有的行数。

    我们最常见的误解也就在这儿,在括号内指定了一列却希望统计结果是行数,而且还常常误以为前者的性能会更好。但实际并非这样,如果要统计行数,直接使用 COUNT(*) ,意义清晰,且性能更好。

    有时候某些业务场景并不需要完全精确的 COUNT 值,可以用近似值来代替,EXPLAIN出来的行数就是一个不错的近似值,而且执行EXPLAIN并不需要真正地去执行查询,所以成本非常低。通常来说,执行 COUNT() 都需要扫描大量的行才能获取到精确的数据,因此很难优化,MySQL层面还能做得也就只有覆盖索引了。如果不还能解决问题,只有从架构层面解决了,比如添加汇总表,或者使用redis这样的外部缓存系统。

    优化关联查询

    在大数据场景下,表与表之间通过一个冗余字段来关联,要比直接使用 JOIN 有更好的性能。如果确实需要使用关联查询的情况下,需要特别注意的是:

    确保 ON 和 USING 字句中的列上有索引。在创建索引的时候就要考虑到关联的顺序。当表A和表B用列c关联的时候,如果优化器关联的顺序是A、B,那么就不需要在A表的对应列上创建索引。没有用到的索引会带来额外的负担,一般来说,除非有其他理由,只需要在关联顺序中的第二张表的相应列上创建索引(具体原因下文分析)。

    确保任何的 GROUP BY 和 ORDER BY 中的表达式只涉及到一个表中的列,这样MySQL才有可能使用索引来优化。

    (责任编辑:admin)