• 用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结果

    原文链接

    官方链接

  • 相关阅读:
    [转]ASP NET 缓存相关介绍及汇总
    比较经典的SQL行转列+分组集联
    平面向量的叉乘
    获得一点到三角形最近点
    检测线段是否有交集
    线段交集点计算
    UE4 移动设备 不显示影子问题
    Unity通过世界坐标系转换到界面坐标位置
    selemium 常用查找方法
    unity导入TexturePacker处理
  • 原文地址:https://www.cnblogs.com/aeolian/p/10216362.html
Copyright © 2020-2023  润新知