You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL 8含ORDER BY的空结果查询耗时过长,求索引优化方案

MySQL 8.0.33大表查询性能优化问题

环境与表结构

使用MySQL 8.0.33社区版,eventiAcc表存储2000万条记录,表结构如下:

CREATE TABLE `eventiAcc` (
  `chiave` int NOT NULL AUTO_INCREMENT,
  `tipo` tinyint NOT NULL,
  `account` int DEFAULT NULL,
  `utente` int DEFAULT NULL,
  `timestp` datetime NOT NULL,
  `dato` varchar(50) DEFAULT NULL,
  `extra` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`chiave`),
  KEY `idx1` (`account`,`tipo`,`timestp`),
  KEY `idx2` (`tipo`,`utente`),
  KEY `idx_timestp` (`timestp`)
) ENGINE=InnoDB AUTO_INCREMENT=40908800 DEFAULT CHARSET=utf8mb3

问题现象

执行无排序的查询时,MySQL使用idx2索引,0.06秒返回空结果:

SELECT chiave, tipo, account, utente, timestp, dato, extra 
FROM eventiAcc 
WHERE utente=25169 
AND tipo=26 
AND dato='aggIndFatt';

但添加ORDER BY timestp DESC LIMIT 1后,查询耗时长达2分8.12秒才返回空结果:

SELECT chiave, tipo, account, utente, timestp, dato, extra 
FROM eventiAcc 
WHERE utente=25169 
AND tipo=26 
AND dato='aggIndFatt' 
ORDER BY timestp DESC LIMIT 1;

推测是MySQL优化器选择了idx_timestp索引,先全表排序再应用WHERE条件,导致性能暴跌。

测试验证结果

  • 不带dato条件的查询返回4826行,耗时0.08秒;
  • 上述查询添加ORDER BY timestp DESC LIMIT 1仅耗时0.01秒;
  • 删除idx_timestp索引后,原慢查询耗时降至0.08秒,但该索引为其他业务查询所需,不能删除。

问题求助

  1. 如何让MySQL 8忽略idx_timestp索引?
  2. 解决该性能问题的最优方案是什么?

解决方案

临时忽略指定索引的方法

可以通过查询语句强制指定索引,避免MySQL选择idx_timestp:

  1. 使用IGNORE INDEX直接排除idx_timestp:
SELECT chiave, tipo, account, utente, timestp, dato, extra 
FROM eventiAcc 
IGNORE INDEX (idx_timestp)
WHERE utente=25169 
AND tipo=26 
AND dato='aggIndFatt' 
ORDER BY timestp DESC LIMIT 1;
  1. 使用FORCE INDEX强制使用idx2索引:
SELECT chiave, tipo, account, utente, timestp, dato, extra 
FROM eventiAcc 
FORCE INDEX (idx2)
WHERE utente=25169 
AND tipo=26 
AND dato='aggIndFatt' 
ORDER BY timestp DESC LIMIT 1;

最优解决方案:创建覆盖联合索引

临时方法只能解决单个查询的问题,最优方案是创建适配该查询的覆盖索引,从根源上优化性能。

当前idx2仅包含(tipo, utente),无法覆盖dato过滤和timestp排序需求。创建以下联合覆盖索引:

CREATE INDEX idx_utente_tipo_dato_timestp ON eventiAcc (utente, tipo, dato, timestp DESC) INCLUDE (chiave, account, extra);

索引设计说明:

  • utente, tipo, dato:按过滤基数从高到低排序,优先过滤掉不符合条件的记录;
  • timestp DESC:直接满足查询的排序需求,避免额外的排序操作;
  • INCLUDE子句:包含查询需要的其他字段,让索引成为覆盖索引,查询时无需回表读取原数据,性能达到最优。

该索引既能快速过滤出符合utente=25169 AND tipo=26 AND dato='aggIndFatt'的记录,又能直接按timestp降序获取第一条数据,即使结果为空也能瞬间返回。


内容的提问来源于stack exchange,提问作者Andrea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:13:29