用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結果

原文鏈接

官方鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM