求解此种情况下为何索引会失效,导致全表扫描?






有没有用到索引,是看Key那一栏,而不是possible_key

索引失效的原因有很多,



大哥我知道是看key,我圈起来possible_key是为了说明这两张边上是有索引(主键)

是啊,所以说,存在索引失效的问题。

这个需要你自己看下什么情况导致的啊,单纯看sql,是看不出来的。

没有表结构等

order by 字段 使用含索引的字段。如主键id

order by 子句的列是有索引的 图中也贴出了建索引的SQL。好的,谢谢兄台,我再看看。

有些索引是没用的。你建的时间索引明显没用到。可能用到的索引里面都没包含那个时间索引

你试试用id把,如果还没解决的话,可以把表发给我。我有空帮你看看

谢谢,表结构如下:


CREATE DATABASE `demo` ;


USE `demo`;


CREATE TABLE `tm_order_info` (

 `id` varchar(50) NOT NULL,

 `goods_id` varchar(20) DEFAULT NULL,

 `user_id` varchar(50) NOT NULL,

 `univalence` int(11) DEFAULT NULL,

 `money` int(11) DEFAULT NULL,

 `num` int(11) DEFAULT '1',

 `status` int(11) DEFAULT '1',

 `order_num` varchar(100) DEFAULT NULL,

 `pay_date` timestamp NULL DEFAULT NULL,

 `create_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,

 PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into `tm_order_info`(`id`,`goods_id`,`user_id`,`univalence`,`money`,`num`,`status`,`order_num`,`pay_date`,`create_date`) values ('1','1','1',12345678,1234,1,1,'123123','2020-07-10 18:44:55','2020-07-10 18:44:58'),('98803754616292453','1','1',12345678,12366191,1,1,'123123','2020-07-08 18:44:55','2020-07-10 18:45:57');


CREATE TABLE `tm_send_records` (

 `id` varchar(20) NOT NULL COMMENT '主键ID',

 `order_id` varchar(20) NOT NULL COMMENT '订单ID',

 PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1;

insert into `tm_send_records`(`id`,`order_id`) values ('1','1');


CREATE TABLE `tm_trademark` (

 `id` varchar(20) NOT NULL,

 `name` varchar(20) NOT NULL,

 `image` varchar(128) DEFAULT NULL,

 PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;


insert into `tm_trademark`(`id`,`name`,`image`) values ('1','阿斯顿发送到','https://xxx.oss-cn-zhangjiakou.aliyuncs.com/icon/trademark/20200709/66925599999500.jpg');


CREATE TABLE `tm_user_info` (

 `id` varchar(50) NOT NULL,

 `phone` varchar(50) NOT NULL,

 `nikename` varchar(500) NOT NULL,

 PRIMARY KEY (`id`) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

insert into `tm_user_info`(`id`,`phone`,`nikename`) values ('1','13309272164','非法字符');


查询语句:


SELECT

toi.id,

toi.status,

toi.univalence,

toi.num,

toi.money,

toi.order_num,

toi.pay_date pay_time,

toi.create_date create_time,

'微信支付' pay_type,

(SELECT COUNT(0) FROM tm_send_records tsr WHERE tsr.order_id = toi.id) remaining,

# 显示关联列则索引失效

tt.image,

tt.name,

tui.phone,

tui.nikename

FROM

tm_order_info toi

LEFT JOIN tm_user_info tui ON toi.`user_id` = tui.`id`

LEFT JOIN tm_trademark tt ON toi.`goods_id` = tt.`id`

LIMIT 20;


我什么都没动

你试着把order_info表的数据多复制几条呢?

你给tm_order_info表建一个组合索引(user_id,goods_id)

今天没空了。该下班了

好,我晚上回去试试,谢谢?

这种时候,你加where 条件 create_date 排除掉 大部分数据,查看执行计划,你会发现 你的索引被用上了

我做过这个尝试,在tm_order_info表的数据量很少的时候,确实会发现索引生效了,但是当数据量超过20条的时候就还是变成了use join buffer (BNL)了。实在是搞不懂啊~

我觉得也许我可以通过Cardinality来得出答案。

你排序了,然而没有 where 帮你检索掉 大部分数据,所以就需要全表扫描了,数据库 优化机制默认会认为使用索引会更慢,所以就不会使用了

其实我更疑问的是,如果再关联查询的时候,我在查询结果中加入了关联表的非主键字段之后就会导致索引失效。但是类似于"select a.name, b.dept_name from a left join b on a.dept_id = b.id"这样的SQL不是经常会用到的关联查询吗?难道这种写法有什么问题吗?

在多表查询中,一般使用组合索引进行查询的。考虑对select 、where、order by中的字段添加索引

你的意思是在这条语句中(select a.name, b.dept_name from a left join b on a.dept_id = b.id)对b表的dept_name加索引吗?


dept_id和name

那么对于这样的业务逻辑,还有其它的处理方式吗?因为如果这样的话,当结果集出现的关联字段较多的话,可能会出现维护索引过多的问题吧?

所以,索引要选那种筛选性较大的字段