MariaDB 10(MyISAM)大表DESC LIMIT 1查询优化求助
解决MariaDB MyISAM下慢查询问题
从你提供的查询和执行计划来看,问题的核心出在索引策略上,咱们一步步拆解分析:
为什么当前查询耗时这么久?
你的需求是获取id=5344的最新一条记录,并计算ceil(rate * 8 / 1000000)。但执行计划暴露了关键问题:
possible_keys: NULL:数据库找不到适合过滤id=5344的索引key: Octets_1_idx:被迫走了datetime相关的单索引(推测是按datetime排序的单独索引)- 此时数据库会按datetime倒序扫描整个索引,逐个检查每条记录的
id是否等于5344,直到找到第一条符合条件的。如果表中id=5344的记录占比很低,或者索引本身体积很大,这个扫描过程就会耗时极久——哪怕最后只返回1条数据。
你删除旧数据、优化表的操作只能解决数据碎片问题,但无法改变索引扫描的逻辑,所以对提速没有帮助。
最优解决方案:创建覆盖联合索引
直接创建一个覆盖联合索引,让数据库能一步定位到目标数据:
CREATE INDEX idx_id_datetime_rate ON db.Octets (id, datetime DESC, rate);
这个索引的优势:
- 先按
id过滤:索引第一列是id,数据库能快速定位到所有id=5344的记录 - 再按
datetime DESC排序:索引第二列已经是倒序排列,所以第一条就是最新的记录 - 包含
rate列:这是覆盖索引,数据库不需要回表读取原始数据文件,直接从索引里就能拿到计算需要的rate值,进一步提升速度
验证效果
创建索引后,重新执行查询并查看执行计划,应该会看到:
type变成ref或rangekey显示为新创建的idx_id_datetime_rateExtra可能会出现Using index(表示用了覆盖索引,无需回表)
此时查询耗时应该会降到毫秒级。
备选方案(如果不想加rate到索引)
如果暂时不想创建覆盖索引,至少要创建(id, datetime DESC)的联合索引:
CREATE INDEX idx_id_datetime ON db.Octets (id, datetime DESC);
这个索引也能让数据库快速定位到id=5344的最新记录,只是需要回表取rate值,速度比覆盖索引略慢,但也远快于当前的查询。
内容的提问来源于stack exchange,提问作者ZCT
相关产品推荐
相关产品推荐

