zoukankan      html  css  js  c++  java
  • 数据库Group by语句调优和Distinct语句调优

    数据库Group by语句调优

    松散索引扫描(Loose Index Scan):性能最好 explain中会有Using index for group-by

    紧凑索引扫描(Tight Index Scan): 性能第二 explain中无明显标识

    临时表(Temporary table): 性能最差 explain中会有Using temporary

    性能依次递减

    优化措施: 避免临时表,使用松散/紧凑索引扫描。

    1、松散索引扫描

    无需扫描满足条件的所有索引键即可返回结果。

    什么是松散索引?

    查询每个员工发到的最小工资?

    SELECT emp_no, MIN(salary)
    FROM salaries
    GROUP BY emp_no
    

     salaries表的索引为emp_no与salary

     分析这条SQL执行情况  

    执行:

    EXPLAIN SELECT emp_no, MIN(salary)
    FROM salaries
    GROUP BY emp_no

     可以发现type为range,Extra为Using index for group-by

    使用松散索引扫描的条件

    1、条件1

    1) 查询作用在单张表上

    2) GROUP指定的所有字段要符合最左前缀原则,且没有其他字段。

     比如索引为index(c1,c2,c3), 如果group by  c1, c2则可以使用松散索引扫描; 但是group by c2, c2; group by c1, c2, c4 则不能使用。

     2、条件2

    如果存在聚合函数,只支持MIN()/MAX(),并且如果同时使用了MIN()和MAX(),则必须作用在同一个字段。聚合函数作用的字段必须在索引中,并且要紧跟GROUP BY所指定的字段。

     比如索引为index(c1,c2,c3), SELECT c1,c2,MIN(c3), MAX(c3) from t1 group by c1,c2 可以使用松散索引扫描。

    3、条件3

    如果查询中存在除GROUP BY指定的列以外的其他部分,则必须以常量的形式出现。

    select c1,c3, from t1 group by c1,c2 :不能使用

    select c1,c3, from t1 where c3 = 3  group by c1,c2 :可以使用

    条件4

    索引必须索引整个字段的值,不能是前缀索引

    比如有字段c1 varchar(20), 但是如果该字段使用的是前缀索引index(c1(10)) 前10个字符,而不是index(c1), 无法使用松散索引扫描

     能使用松散索引扫描的SQL一览

    假设index(c1,c2,c3) 作用在表t1(c1,c2,c3,c4), 下面这些SQL都能使用松散索引扫描

    不能使用松散索引扫描的SQL

    假设index(c1,c2,c3) 作用在表t1(c1,c2,c3,c4), 下面这些SQL不能使用松散索引扫描 

    特定聚合函数用法能用上松散索引扫描的条件

     假设index(c1,c2,c3) 作用在表t1(c1,c2,c3,c4), 下面这些SQL都能使用松散索引扫描 

     select count(distinct c1), sum(distinct c1) from t1;

    select count(distinct c1, c2), count(distinct c2, c1) from t1;

    2、紧凑索引扫描

    需要扫描满足条件的所有索引键才能返回结果

    性能一般比松散索引扫描差,但一般都可接受。


    EXPLAIN SELECT emp_no, SUM(salary)
    FROM salaries
    GROUP BY emp_no

    聚合函数时sum,肯定无法使用松散索引扫描,退而求其次,使用紧凑索引扫描。执行后结果如下图所示:

     type是index,发生了全索引扫描。Extra为Using index,表示使用了覆盖索引。

    3、临时表

    紧凑索引扫描也没有办法使用的话,MySQL将会读取需要的数据,并创建一个临时表,用临时表实现GROUP BY操作

    -- employees 表没有索引
    EXPLAIN
    SELECT MAX(hire_date)
    FROM employees
    GROUP BY hire_date

     

     Extra: Using temporary 表示使用了临时表。

    4、如何优化GROUP BY 语句

    如果GROUP BY使用了临时表,想办法用上松散索引扫描或紧凑索引扫描。(优化方案是创建索引)

    5、DISTINCT优化

    distinct是在group by操作之后,每组只取1条

    和group by优化思路一样

    作者:Work Hard Work Smart
    出处:http://www.cnblogs.com/linlf03/
    欢迎任何形式的转载,未经作者同意,请保留此段声明!

  • 相关阅读:
    atitit.ntfs ext 文件系统新特性对比
    Atitit.图片木马的原理与防范 attilax 总结
    Atitit.图片木马的原理与防范 attilax 总结
    Atitit.jdk java8的语法特性详解 attilax 总结
    Atitit.jdk java8的语法特性详解 attilax 总结
    Atitit.远程接口 监控与木马   常用的api 标准化v2 q216
    Atitit.远程接口 监控与木马   常用的api 标准化v2 q216
    Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结
    Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结
    Atitit.跨平台预定义函数 魔术方法 魔术函数 钩子函数 api兼容性草案 v2 q216  java c# php js.docx
  • 原文地址:https://www.cnblogs.com/linlf03/p/14207887.html
Copyright © 2011-2022 走看看