mysql索引最左原则和索引什么时候会失效的场景测试

-- mysql 建表语句
CREATE TABLE tb_test_qiu ( id INT PRIMARY KEY, a TINYINT, b TINYINT, c TINYINT )
-- tb_test_qiu表 插入联合索引
ALTER TABLE `tb_test_qiu` ADD INDEX `testabc` (`a`, `b`, `c`) ;

-- 索引最左原则和索引什么时候会失效的场景测试:

-- 实际上创建了 a,ab,abc索引,其中ab,abc的字母调换顺序完全不影响,也是命中索引。

-- 测试a
explain select id,a,b,c from tb_test_qiu where a = 1 -- 索引
explain select id,a,b,c from tb_test_qiu where a > 1 -- range索引
-- 测试ab
explain select id,a,b,c from tb_test_qiu where b = 1 -- 无索引
explain select id,a,b,c from tb_test_qiu where b = 1 and a = 1 -- 索引
explain select id,a,b,c from tb_test_qiu where a = 1 and b = 1 -- 索引
explain select id,a,b,c from tb_test_qiu where b = 1 and a > 1 -- range索引
explain select id,a,b,c from tb_test_qiu where a > 1 and b = 1 -- range索引
-- 测试abc
explain select id,a,b,c from tb_test_qiu where c = 1 -- 无索引
explain select id,a,b,c from tb_test_qiu where b = 1 and c = 1 -- 无索引(index)
explain select id,a,b,c from tb_test_qiu where c = 1 and b = 1 -- 无索引
explain select id,a,b,c from tb_test_qiu where a = 1 and b = 1 and c > 0 -- range索引 (范围索引)
explain select id,a,b,c from tb_test_qiu where a = 1 and c = 1 and b = 1 -- 索引
explain select id,a,b,c from tb_test_qiu where b = 1 and a = 1 and c = 1 -- 索引
explain select id,a,b,c from tb_test_qiu where b = 1 and c = 1 and a = 1 -- 索引
explain select id,a,b,c from tb_test_qiu where c = 1 and a = 1 and b= 1 -- 索引
explain select id,a,b,c from tb_test_qiu where c = 1 and b = 1 and a= 1 -- 索引
explain select id,a,b,c from tb_test_qiu where c BETWEEN 1 and 2 and b = 1 and a= 1 -- range索引 (范围索引)
explain select id,a,b,c from tb_test_qiu where c <> 2 and b = 1 and a= 1 -- range索引 (范围索引)
explain select id,a,b,c from tb_test_qiu where a in (1) -- 索引(a = 1,命中索引)
explain select id,a,b,c from tb_test_qiu where a in (1,2,3) -- range索引 (in里的数据小于表里的总数据)
explain select id,a,b,c from tb_test_qiu where a in (1,2,3,4,5) -- 无索引(in里的数据>=表里的总数据)
explain select id,a,b,c from tb_test_qiu where a like '%1' -- 无索引
explain select id,a,b,c from tb_test_qiu where a like '%1%' -- 无索引
explain select id,a,b,c from tb_test_qiu where a like 'ddd%'-- 有索引
explain select id,a,b,c from tb_test_qiu where a is not null -- range索引
explain select id,a,b,c from tb_test_qiu where a is null -- 索引
-- is not null不管什么情况下都不会走索引(默认是range),is null在字段允许为空时会使用索引
-- 要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

对于索引失效问题工作中总结:
order by 的条件会影响正常的索引失效
    例如:主键是id,优化器会优先选择主键id索引,使正常的索引或者联合索引不被使用,既失效
>= <= 和 between也会导致索引失效    
    例如:AND time_range_start >= '2023-10-02' and time_range_end <= '2023-10-02' 因为不是同一个字段,所以范围没有界限,导致失效
    AND time_range_start >= '2023-10-02' and time_range_start <= '2023-10-02' 因为是同一个字段,有范围界限,索引生效
对于联合索引的工作中的理解;
举例:abcd_index(a,b,c) 的联合索引会有多少种组合情况命中索引?
    1.a
    2.b
    3.c
    联合索引的每个字段都是一个单独的索引,如上1,2,3所示
    联合索引组合的情况,必须是有最左边的字段a出现,不然任何组合都失效
    联合索引针对where条件的顺序没有要求,既ba,ca,cba都会命中联合索引(原理是查询优化器会自动进行排序优化,再进行索引匹配,但是ba只能部分命中索引,比如只能命中a【这是因为最左原则问题的体现】,cab只能命中ab索引,cba也只能命中a所以,bc都不能命中【最左原则必须有a索引的出现】)
    4.ab,ba 
    5.ac,ca
    6.abc,acb, bac,bca,cab,cba
如果where条件多个字段,
    例如: 1.a  = 1 and b = 1 and f = 1 and c = 1,也会正常命中abc索引,查询优化器只查找where条件里跟索引相同的字段,f不是索引字段,也不会影响索引失效
           2.a = 1 and b = 1 and f = 1 ,会命中 ab 索引,f不是索引字段,不影响索引失效
           总结:查询优化器会主动在where条件中找出符合abcd_index(a,b,c)联合索引的某个组合索引,如上举例所示。

索引顺序和where条件的顺序没有关系,优化器会主动调整where条件后面的顺序和索引顺序一致
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL匹配原则失效场景包括: 1. 如果在查询条件中使用了函数或者表达式,则可能导致最匹配失效。例如,查询语句中使用了函数或者表达式,如`SELECT * FROM users WHERE age + 10 = 35 AND name = 'John'`,这种情况下MySQL无法使用索引,因为它无法对函数或者表达式进行索引。 2. 如果在查询条件中使用了OR操作符,则可能导致最匹配失效。例如,查询语句中使用了OR操作符,如`SELECT * FROM users WHERE name = 'John' OR age = 25`,这种情况下MySQL也无法使用索引,因为它无法同时对两个列进行索引。 3. 如果在查询条件中使用了不等于号(<>),则可能导致最匹配失效。例如,查询语句中使用了不等于号,如`SELECT * FROM users WHERE name <> 'John' AND age = 25`,这种情况下MySQL也无法使用索引,因为它无法对不等于号进行索引。 4. 如果在查询条件中使用了LIKE操作符,并且通配符出现在边,则可能导致最匹配失效。例如,查询语句中使用了LIKE操作符,如`SELECT * FROM users WHERE name LIKE '%John' AND age = 25`,这种情况下MySQL也无法使用索引,因为它无法对边的通配符进行索引。 一个不走索引的案例是,假设我们有一个名为users的表,其中包含id、name和age三列。如果我们在使用查询语句时,使用了以下条件: ``` SELECT * FROM users WHERE name='John' AND age>25; ``` 如果我们在表中创建了一个包含name和age两列的联合索引,则MySQL使用该联合索引进行匹配。但是,由于age列上使用了大于号,所以MySQL无法使用该索引,因为索引只能用于等于和小于操作。因此,MySQL不得不扫描整个表来查找匹配的行,这导致查询性能变差。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值