mysql索引失效问题记录

背景:在一次开发中,需要查询促销活动商品表,查询条件是sku_id,走了全表扫描没走索引,学习记录下索引失效原因。

1.条件字段带函数操作

--交易日志表
CREATE TABLE `trade_log` (
	`id` INT ( 11 ) NOT NULL,
	`trade_id` VARCHAR ( 32 ) DEFAULT NULL,
	`operator` INT ( 11 ) DEFAULT NULL,
	`create_time` datetime DEFAULT NULL,
	`update_time` datetime DEFAULT NULL,
	PRIMARY KEY ( `id` ),
KEY `idx_tradeid` ( `trade_id` ),
KEY `idx_create_time` ( `create_time` )) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
  • 需求:统计2021年的订单数
--sql你可能会这么写
SELECT
count(*)
FROM
trade_log
WHERE
YEAR(create_time)=2021;

你会发现sql可能需要一定的时间,这是因为InnoDB表为索引组织表,每个索引对应这一个B+树,对条件使用函数破坏了索引的有序性,虽然走索引,但是优化器会放弃搜索树功能,进行全索引扫描。

2.隐式类型转换

看下这条sql

select count(*) from trade_log where trade_id=1256;

其中trade_id字段是varchar,而输入的参数是整型的,所以包含了隐式类型转换。
在mysql中字符串和数字进行比较,会将字符串转换为数字。

比较数字转换规则这里有一个简单的方法,看 select “10” > 9 的结果:

  • 如果规则是“将字符串转成数字”,那么就是做数字比较,结果应该是 1;
  • 如果规则是“将数字转成字符串”,那么就是做字符串比较,结果应该是 0。

那么第一条语句对于优化器来说就等价于第二条sql,也就是说,这条语句触发了我们上面第一点说到的规则:对索引字段做函数操作,优化器会放弃走树搜索功能。

select count(*) from trade_log where trade_id=1256;
select count(*) from tradelog where CAST(tradid AS signed int) = 1256;

3.隐式字符编码转换

当两个表的字符集不同,关联查询时不会走索引,原因同上第一点,涉及到了mysql字段带函数操作。

不会走索引

EXPLAIN SELECT * FROM activityluck_attribute WHERE id + 1= 2

养成一个好习惯吧,开发的时候explain一下。

おすすめ

転載: blog.csdn.net/weixin_45582733/article/details/118251493