我的表中有大约 4.2 亿条记录。 user_table
的 colC
列只有一个索引。下面的查询返回大约 150 万条记录,基于
colC
。但是不知何故没有使用索引并在 20 到 25 分钟内返回记录
select colA ,ColB , count(*) as count
from user_table
where colC >='2019-09-01 00:00:00'
and colC<'2019-09-30 23:59:59'
and colA in ("some static value")
and ColB in (17)
group by colA ,ColB;
但是当我执行强制索引时,它开始被使用并仅在 2 分钟内返回记录。我的问题为什么MYSQL在获取时默认不使用索引 索引的时间要少得多?我已经重新创建了索引并进行了修复,但默认情况下无法使用它。
另一个信息观察是相同的查询(没有强制索引)适用于前几个月(具有相同的数据量)。
更新 Evert询问的细节
创建表 USER_TABLE (
id bigint(20) 无符号 NOT NULL AUTO_INCREMENT,
COLA varchar(10) 默认为空,
COLB int(11) 默认为空,
COLC 日期时间默认为空,
....
主键(id),
KEY
colA(
COLA),
KEY
colB(
COLB),
KEY
colC(
COLC)
) ENGINE=MyISAM AUTO_INCREMENT=2328036072 DEFAULT CHARSET=latin1 |
最佳答案
为了获得更好的性能,您可以尝试使用复合索引 .. 基于 where 子句中涉及的列
并尝试更改内部连接中的 IN 子句
假设您的 IN 子句内容是一组固定值,您可以使用联合(或具有所需值的新表)
例如使用联合(如果 IN 子句是子查询,你可以做类似的事情)
select user_table.colA ,ColB , count(*) as count
from user_table
INNER JOIN (
select 'FIXED1' colA
union
select 'FIXED2'
....
union
select 'FIXEDX'
) t on t.colA = user_table.colA
where colC >='2019-09-01 00:00:00'
and ColB = 17
group by colA ,ColB;
您还可以在表 user_table 的列上添加复合索引
colA, colB, colC
对于与 mysql 查询优化器使用的元素相关的元素,用于决定在几个方面使用索引,并且查询优化器为所有这些分配成本
任何你应该考虑的事情
- Where子句涉及的列
- 表的大小(通常情况下不是连接中表的大小)
- 估计将获取多少行(以决定是使用索引还是简单地扫描表)
- 如果数据类型在 jion 和 where 子句中的列之间匹配或不匹配
- 函数或数据类型转换的使用,包括排序规则的错误
- 索引的大小
- 索引的基数
所有这些选项都被评估为成本,这导致索引选择
在你的情况下,作为日期的 colC 可能意味着数据转换(将文字值视为字符串)并且为此未选择索引..
也是为了这个,我建议了一个复合索引,其中最左边的列与非转换值相关
关于mysql - 为什么 Index 只在强制使用时使用,默认不使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58551537/