sqlin会导致索引失效吗(sql in 索引是否有效)

http://www.itjxue.com  2023-01-27 01:11  来源:未知  点击次数: 

sql in语句的性能问题

每个机票订单含有多个票,用符合条件的订单List,去查询对应的票List。

两张表的关联方式是用一个特性的key关联,其中包含,代理商区分标志,订单号,订单类型等,是一个长度在30~50之间的varchar

遍历list一条一条查的话,IO太多,显然不合适。我们就想到用in来实现批量查询

在beta测试时,库中表里只有一个月的数据,大约在1000万左右,测试时没有发现问题。

到了线上之后,发现查询数据非常慢,两万左右的in条件,查询起来,时间在10分钟左右,显然出现了慢查询。

针对这个问题,做了几个测试,看了下执行计划,如下所示

事实上我们看到,在in语句中数据量不大的情况下,索引是有效的,不过这个数量已经是极限了。

下面是我的语句

这里在in里面包含了三万条数据,索引实效了。

这里我们首先想到,强制使用索引会不会有所帮助如下

但是,事实上并没有效果,这是结果

解下来我们分析一下,两个问题,索引为什么会失效

这个问题需要从两个方面入手

1.索引区分度

2.预计扫描行数

3.优化器的选择

先看第一个,索引的区分度,经过随机采样,看着内容还是很高的。

预计扫描行数

预计扫描行数的话,如前两图所示,基本都走了全表扫描。

优化器的选择

优化器选择时,衡量了回表等操作,综合考虑,这里没有办法继续下去了,只能问到DBA了。

在数据表大时,索引负重较大,同样的情况下,in语句里面数据条数够大时,索引会失效,可以通过force index尝试一下,不过成功的可能行很小,尽量分批去查找,批次数量可配置。

Db2 中in能用上索引吗

IN肯定会走索引,但是当IN的取值范围较大时会导致索引失效,走全表扫描。

mysql 避免索引失效

where条件==order by 条件==group by 条件 按顺序遵守 最佳左前缀法则

假设创建了复合索引:a,b,c

不在索引列上做任何的操作(计算、函数、显式或隐式的类型转换),否则会导致索引失效而转向全表扫描

1、字符不加单引号会导致索引失效

name字段为varchar类型

这条sql发生了隐式的类型转换:数值==字符串。所以导致了全表扫描,索引失效

应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:

mysql中的范围条件有:in/not in、 like、 、BETWEEN AND ;

后面的索引失效

in会导致索引全部失效!!!

BETWEEN AND 范围条件不会导致索引失效!!!

尽量让索引列和查询列一致;减少select * 的使用

1、查询表结构

2、查询表的索引结构

联合索引:name,age,post;说明add_time字段没有添加索引

3、查看select * 的执行计划

4、查看 select name,age,pos的执行计划

5、如果select只用一部分索引

like以通配符开头(’%abc…’)mysql索引失效会变成全表扫描的操作。

解决:可以使用 覆盖索引 来解决这个问题!

1、先查看表上的索引

id、name、age、pos 四个字段上都有索引; 注意:name是联合索引中的第一个,带头大哥!

2、查看表结构

有个add_time字段没有用到索引

3、查看执行计划

使用UNION ALL

假设创建了联合索引 x(a,b,c)

ps:like虽然也是范围查询但是区别于、,%用在最前面就只用到索引a了;%用在最后面可以用到a+b+c!

下面的sql几乎违背了上面的所有原则,索引依然全部生效。因为select是索引覆盖的,select里不包含没有建立索引的字段。因此总是用到索引的。可以看出来索引覆盖在sql优化中的作用性

(责任编辑:IT教学网)

更多

推荐软件水平考试文章