mysql group by相关问题

148 阅读3分钟

1 sql mode参数解释

1 ONLY_FULL_GROUP_BY
  对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,
  那么将认为这个SQL是不合法的,因为列不在GROUP BY从句中。
2 STRICT_TRANS_TABLES
  在该模式下,如果一个值不能插入到一个事务表中,
  则中断当前的操作,对非事务表不做任何限制。
3 NO_ZERO_IN_DATE
  在严格模式,不接受月或日部分为0的日期。
  如果使用IGNORE选项,我们为类似的日期插入'0000-00-00'。
  在非严格模式,可以接受该日期,但会生成警告。
4 NO_ZERO_DATE
  在严格模式,不要将 '0000-00-00'做为合法日期。你仍然可以用IGNORE选项插入零日期。
  在非严格模式,可以接受该日期,但会生成警告。
5 ERROR_FOR_DIVISION_BY_ZERO
  在严格模式,在INSERTUPDATE过程中,如果被零除(或MOD(X, 0)),则产生错误(否则为警告)。
  如果未给出该模式,被零除时MySQL返回NULL。
  如果用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告,但操作结果为NULL6 NO_AUTO_CREATE_USER 
  防止GRANT自动创建新用户,除非还指定了密码。
7 NO_ENGINE_SUBSTITUTION
  如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,
  用默认的存储引擎替代,并抛出一个异常。

mysq5.6 和 mysql5.7 orderBy + groupBy 表现的区别

mysql5.7 Derived table:
  Derived table是自查询的一种处理形式,在5.7之前的版本,
  都是把Derived table进行生成,然后以临时表的形式保存,然后进行join等形式查询.
  但是5.7之后,对Derved table做了新特性处理,允许符合条件的自查询直接和副查询进行join等操作.
造成的问题:
  需求: 现在需要查询一个表中按照name分组之后数据查询id最大的那条记录进行返回
  select * from 
    (select * from tableName where xxx order by id desc) as a 
      group by name order by id desc limit 4;
  mysql5.6写法:
    实现结果: 取表中按照name分组之后数据,取每一组中id最大的那条记录,对最终结果按照id进行倒叙排列,取4条记录
  mysql5.7:
    实现结果: 取表中按照name分组之后,取第一条id记录,之后对最终结果按照id排序取4条
  我们发现自查询中的order by id desc没有生效,少了一个 DERIVED 操作估计是内部优化了,
  认为 ORDER BY 在这种语法中可忽略有 LIMIT 限制涉及排序后的结果,
  不会忽略 ORDER BY,可以达到预期
  解决办法: 
    select * from 
        (select * from tableName where xxx order by id desc limit xxx) as a 
        group by name order by id desc limit 4; 
        or 对自查询使用distinct处理,总之对结果集处理
        不要让服务认为order by是可以优化的 增加limit之后则无法使用优化条件,则会达到预期

optimizer_switch 介绍

SHOW VARIABLES LIKE 'optimizer_switch'; 查看优化器的一些参数

index_merge=on: 允许使用索引合并优化。
  介绍: 是否能使用多索引的情况,多用作or或者union条件的时候,一条sql使用多个索引,
  并且对多个索引的结果集进行合并
  什么是Index Merge?Index Merge的限制有哪些?
如果查询中使用到了不同的索引,可以对不同索引的条件分别进行范围扫描,
然后将扫描结果合并得到最终的结果,这就是Index Merge。
限制:只能合并同一个表的索引扫描结果,不能跨表合并。此外,无法对fulltext索引进行合并

index_condition_pushdown=on: 允许下推索引条件到存储引擎层。
materialization=on: 允许物化子查询。
derived_merge=on: 允许合并派生表。