zoukankan      html  css  js  c++  java
  • 用where导致group by分组字段的索引失效

    把两个单独的索引合并成一个组合索引,即把where条件字段的索引和group by的分组字段索引组合成一个。

    如果分组的字段需要用函数处理,可以用索引函数

    Generated Column(函数索引)

    mysql5.7版本,函数索引用虚拟列,virtual是查询时在内存中计算,而store是计算好后存放在磁盘中。一般作为索引,默认用virtual。

    语法:

    <type> [ GENERATED ALWAYS ] AS ( <expression> ) [ VIRTUAL|STORED ] [ UNIQUE [KEY] ] [ [PRIMARY] KEY ] [ NOT NULL ] [ COMMENT <text> ]

    修改table添加一个新列,由函数处理已有字段自动生成。

    新建虚拟列

     ALTER TABLE tblName ADD virtualField varchar(50) GENERATED ALWAYS AS (FROM_UNIXTIME(bus_remind.arrivingTimeStamp)) virtual;

    删除虚拟列

    alter table tblName drop column fieldName;

    例子

    组合索引如下

    sql语句

    SELECT
        avg(arrivingBattery) AS battery
    FROM
        bus_remind 
    WHERE
        parkingCode = '101001' 
    GROUP BY 
        DATE_FORMAT( FROM_UNIXTIME(arrivingTimeStamp ), '%Y-%m-%d %H:%i' )

    explain结果

    分析原因:

    分组字段根据分钟分组(对字段进行函数处理)导致抛弃索引。

    解决方案:

    复合索引使用虚拟列技术,将虚拟列作为索引,Sql如下

    /*创建*/
    ALTER TABLE bus_remind ADD virtualArrivingTimeStamp char(16) GENERATED ALWAYS AS (DATE_FORMAT(FROM_UNIXTIME(arrivingTimeStamp),'%Y-%m-%d %H:%i')) VIRTUAL comment '来车时间函数索引列';
    /*删除*/
    alter table bus_remind drop column virtualArrivingTimeStamp

    复合索引更改为(版本必须为5.7及以上)

    sql语句更改

    SELECT
        avg(arrivingBattery) AS battery
    FROM
        bus_remind 
    WHERE
        parkingCode = '101001' 
    GROUP BY 
        virtualArrivingTimeStamp

    explain结果

    原文链接

    官方链接

  • 相关阅读:
    网络流 学习笔记
    回文自动机PAM 学习笔记
    后缀自动机SAM 学习笔记
    题解 CF1207G Indie Album
    题解 CF163E e-Government
    AC自动机 学习笔记
    CCF冬令营Day1上午
    不编译AC记录
    生成函数 抄写笔记
    FFT NTT 学习笔记
  • 原文地址:https://www.cnblogs.com/aeolian/p/10216362.html
Copyright © 2011-2022 走看看