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

MariaDB中count(*)用索引但select *未用合适索引的优化求助

问题分析

执行count(*) from table1 WHERE name like 'done%'时,name索引是覆盖索引(仅需统计行数,无需回表取全量数据),因此优化器选择使用该索引;而执行select *时,若用name索引则需要回表获取所有列数据——由于符合条件的行数(913万)接近总数据量的一半(1826万),优化器评估回表的IO成本高于全表扫描,最终选择全表扫描。

解决方案

以下是无需修改查询语句的可行方案:

1. 创建覆盖索引

创建以name开头、包含所有表列的覆盖索引,这样select *可直接从索引中获取所有数据,无需回表,优化器会优先选择该索引:

CREATE INDEX idx_name_covering ON table1 (name, idsite, date1, date2, period, ts_archived, value);

注:InnoDB中主键列会自动包含在二级索引中,因此无需手动添加idarchive。

2. 更新统计信息

若优化器依赖的统计信息不准确,可能导致成本判断错误。执行以下语句更新表的统计信息,帮助优化器做出更合理的选择:

ANALYZE TABLE table1;

3. 调整优化器成本参数

通过调整成本权重,让优化器更倾向于使用索引而非全表扫描:

  • 增大全表扫描的成本权重(让全表扫描看起来更昂贵):
    SET GLOBAL read_rnd_cost = 4; -- 默认值为2,可根据实际测试调整
    
  • 降低索引扫描的成本权重:
    SET GLOBAL read_cost = 1; -- 默认值为1,若当前值更高可调整
    

注:参数调整需结合实际业务场景测试,避免影响其他查询。

4. 修改主键顺序(需评估影响)

若业务允许,可将联合主键调整为(name, idarchive),这样主键索引本身就是以name开头的有序索引,select *时可直接利用主键索引进行范围扫描,无需回表:

ALTER TABLE table1 DROP PRIMARY KEY, ADD PRIMARY KEY (name, idarchive);

此方案需评估对其他依赖原主键的查询、业务逻辑的影响,谨慎操作。

5. 调整优化器开关

启用prefer_ordering_index开关,让优化器优先选择能提供有序结果的索引(即使成本略高):

SET GLOBAL optimizer_switch = 'prefer_ordering_index=on';

该开关会让优化器更倾向于使用索引扫描,而非全表扫描后排序,适用于此类范围查询场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:20:16