ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于组合索引的第二列为in时是否可用走索引的问题

2021-05-11 09:58:48  阅读:185  来源: 互联网

标签:00 可用 -- 索引 tlzl mysql where 列为


组合索引的第二列为in时是否可用走索引?当时面试直接把我问蒙了。一般来说in会等价改写成or,然后走索引。比如

where a in (1,2)

等价于

where a=1 or a=2

在oracle中肯定会这样去改写,所以该走索引的还是会走索引。但是这个条件放在组合索引的第二列呢?

首先等价改写同样成立,比如

where a in (1,2) and b=0

等价于

where (a=1 or a=2) and b=0

优化器是否会这样做呢?这只有测试了才知道

 

oracle测试

 --单列索引
 create index idx_tlzl on tlzl(a);

  1* select * from tlzl where a in (1,2)
-----------------------------------------------------------------------------------------
| Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |          |     2 |    40 |     1   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR             |          |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| TLZL     |     2 |    40 |     1   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | IDX_TLZL |     4 |       |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("A"=1 OR "A"=2)



--复合索引
create index idx_tlzl2 on tlzl(b,a);


--仅指定第二列的条件时,oracle选择走全表扫描
--其实oracle还有索引跳跃扫描的方案,因为b列只有1个值,全表扫描的效率还是要高一些
SQL> select * from tlzl where a in (1,2);


Execution Plan
----------------------------------------------------------
Plan hash value: 925964718

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |    40 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TLZL |     2 |    40 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A"=1 OR "A"=2)
--oracle做了等价改写,in改写成or



--第一列和第二列都有条件时,可以走索引,索引范围扫描
--且做了等价改写
SQL> select * from tlzl where a in (1,2) and b='a';


Execution Plan
----------------------------------------------------------
Plan hash value: 3195115994

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |     2 |    40 |     2   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR  |           |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| IDX_TLZL2 |     2 |    40 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("B"='a' AND ("A"=1 OR "A"=2))

 

mysql测试


--单列索引
mysql> create index idx_tlzl on tlzl(a);


--单列索引时,条件为in时,mysql可以走索引,走索引范围扫描range
mysql> explain select * from tlzl where a in (1,2);
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | tlzl  | NULL       | range | idx_tlzl      | idx_tlzl | 5       | NULL |    2 |   100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.06 sec)


--符合索引
mysql> create  index idx_tlzl2 on tlzl(b,a);

--符合索引只有第二列的条件
--mysql走了索引,但是是index,表示索引全扫描
mysql>  explain select * from tlzl where a in (1,2);
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | tlzl  | NULL       | index | NULL          | idx_tlzl2 | 38      | NULL | 1000 |    20.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.03 sec)


--符合索引有第一列和第二列的条件
--mysql可以走索引,索引范围扫描
mysql>  explain select * from tlzl where a in (1,2) and  b='a';
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | tlzl  | NULL       | range | idx_tlzl2     | idx_tlzl2 | 38      | NULL |    2 |   100.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.03 sec)   

 

 

总结:

1.无论是理论上还是实际上,组合索引的第二列为in是可以走索引的

2.有些细枝末节确实不太容易提前测试到,但是要相信自己的逻辑推理判断

标签:00,可用,--,索引,tlzl,mysql,where,列为
来源: https://blog.csdn.net/qq_40687433/article/details/116640754

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有