podman
(xiaoshan)
April 28, 2025, 7:28am
1
sql如下:
SELECT *
FROM user
WHERE is_deleted = 'N'
AND transaction_type IN (232, 330)
AND gmt_created >= '2025-01-15 00:00:00'
AND gmt_created < '2025-02-15 00:00:00';
index 情况,gmt_created存在索引,
执行计划分析如下:
{
"type": "ALL", // 全表扫描(最差访问方式)
"possible_keys": "gmt_created",
"key": null, // 实际未使用索引
"rows": 2,681,650, // 扫描268万行
"filtered": 0.41, // 仅0.41%数据符合条件
"Extra": "Using where" // 需逐行过滤数据
}
很奇怪,为啥不走gmt_created这个索引,而且有时候过一会,优化器又走了索引,但是大部分都是走全标扫描
大佬们,这么什么情况,优化器反复横跳?
3 Likes
admini
(admini)
April 28, 2025, 7:32am
2
你把其他 2 个条件去掉,看是不是走索引,是其他 2 个条件导致的吧。
1 Like
podman
(xiaoshan)
April 28, 2025, 7:39am
3
{
"select_type": "SIMPLE",
"partitions": null,
"type": "ALL",
"possible_keys": "gmt_created",
"key": null,
"key_len": null,
"ref": null,
"rows": 2113132,
"filtered": 17.78,
"Extra": "Using where"
}
一样,不好用,很奇怪,索引区分度也是有的,符合条件的数据仅仅占比,17.78%
1 Like
admini
(admini)
April 28, 2025, 7:50am
4
记一次Mysql不走日期字段索引的原因_mysql日期条件不走索引-CSDN博客
我给忘记了。类似 in 也有数据量问题,在一定范围内走索引,一定范围内走全表。
2 Likes
podman
(xiaoshan)
April 28, 2025, 8:00am
5
对,和结果集合数据量有很大关系,符合条件的数据基本占比在10%到15%左右,而且原始SQL,in的条件是没有索引,去掉了也是不走索引,想让走索引,只能force index了
1 Like
podman
(xiaoshan)
April 28, 2025, 8:42am
8
目前查询的资料,感觉这个很有道理,涉及到随机IO和顺序IO:
目前有效数据占比在15%到35%之间,因为如果走了gmt_created 索引,就要走id回表查询,因为是按照gmt_created 排序来的,id是无序的,回表就是一个随机磁盘IO,随机IO的耗时远远大于顺序IO的耗时,如果走全标扫描就是一个顺序IO,优化器认为全表的顺序IO优于大批量的随机IO
1 Like
niubikid
(千禧年学会上网)
April 28, 2025, 8:44am
9
看看你的表有多少数据,数据量太少的话,全表扫表比走索引更快
1 Like
podman
(xiaoshan)
April 28, 2025, 8:48am
10
索引扫描成本=索引IO成本+回表IO成本+过滤CPU成本>全表扫描成本
1 Like
blazeb
(pp)
April 28, 2025, 8:53am
13
看你这个 transaction_type,类型都200了,是不是有200多种类型? 有的话,可以在这里建一个索引
1 Like
transaction_type 是交易类型吧?交易类型应该不会有200多种吧
1 Like
Alickx
(李卤味同学仔)
April 28, 2025, 9:07am
15
可以尝试一下 force index 强制走索引,看看慢不慢
1 Like
走in了,少量的in条件会直接走这个,大概100条以上才会走其他索引。或者你用联合索引试一下
1 Like
通俗点讲,你2个in条件,在优化器看来就是固定的条件,固定的肯定是优于你下面的时间范围的,而大量的in条件,这分散一个,那分散一个反而又不如范围条件了
1 Like
听腾讯数据库大佬说,mysql 8 的话 IN 在 1000 以下的都问题不大
2 Likes