abc 联合索引查 bc 走不走索引

2020-03-24 08:31:52 +08:00
 gssong

abc 联合索引查 bc 走不走索引 我觉得按照最左前缀匹配不走,可是面试官说走,说看看 MySQL 内部优化啥的,有没有大佬解答一下

9273 次点击
所在节点    MySQL
56 条回复
jamesz
2020-03-24 11:49:06 +08:00
索引跳跃扫描算法可以不走前缀
qW7bo2FbzbC0
2020-03-24 12:09:24 +08:00
如果 A 是主键的话,可以走索引,如果不是,不可
gy123
2020-03-24 12:21:57 +08:00
根据 select 字段决定,如果查字段只有索引字段,则可能走,因为不需要回表直接遍历索引树即可,避免查询查询主表中大量数据,其实还是看内部优化器
Jooooooooo
2020-03-24 12:47:13 +08:00
答案是不走

只查 bc 不需要回表也能叫走索引吗? 是这么定义的吗?
cholerae
2020-03-24 13:04:53 +08:00
有可能走啊,mysql 8.0 有 index skip scan 。
xiaowangge
2020-03-24 13:16:19 +08:00
MySQL 8.0 doc https://dev.mysql.com/doc/refman/8.0/en/multiple-column-indexes.html



SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;



If an index exists on (col1, col2, col3), only the first two queries use the index. The third and fourth queries do involve indexed columns, but do not use an index to perform lookups because (col2) and (col2, col3) are not leftmost prefixes of (col1, col2, col3).

如果在(col1,col2,col3)上存在索引,则只有前两个查询使用该索引。 第三和第四个查询确实涉及索引列,但不使用索引来执行查找,因为(col2)和(col2,col3)不是(col1,col2,col3)的最左前缀。
nekoneko
2020-03-24 14:48:39 +08:00
走了也没走
如果有 abcd 列,查 bc 用 bc 做 where 条件,那么会遍历索引
如果查 bcd 列,用 bc 做 where 条件,那么不走索引
cxshun
2020-03-24 16:47:36 +08:00
要分几种情况:
1 、假设你的表就 a,b,c 三个字段,那么你建了(a,b,c)这样的索引,然后按 b,c 搜索(即 select * from t where b = xx and c = xx ),这样会走
为什么走索引呢,主要是因为查询的所有字段在索引中都可以找到,根本就不需要回表,直接覆盖索引了
2 、假设你的表有 a,b,c,d 四个字段,那么你建了(a,b,c)这样的索引,然后按 b,c 搜索(即 select * from t where b = xx and c = xx ),那么此时就不会走索引了,因为走了索引也需要回表,对性能优化没太大用处,当然,你可以把索引改为(a,b,c,d ),然后又可以命中了。
vindurriel
2020-03-24 17:47:37 +08:00
即使 mysql 有优化 做功能也不应该依赖这个 老老实实建好索引才是正确的选择 否则换个 db 甚至换个版本就出问题
lucky215
2020-03-24 18:21:26 +08:00
@cxshun 说的靠谱
再补充下,如果在 a,b,c,d 四个字段的情况下,select b,c from t where b = xx and c = xx,也是会走索引的,因为还是覆盖到了
CRVV
2020-03-24 18:22:02 +08:00
这个问题经常有人问,标准答案是不走。

至于到底走不走,必须要说清楚是哪个数据库,哪个版本,表里有多少行,每个字段是什么类型,每个字段的取值范围。基本上没人知道这些问题的答案,所以 PostgreSQL 的文档说的是

This index could in principle be used for queries that have constraints on b and/or c with no constraint on a — but the entire index would have to be scanned, so in most cases the planner would prefer a sequential table scan over using the index.

拿文档来回答这个问题,那就是可以走索引( This index could in principle be used )

具体来说,假设三个字段里,a 是性别,b 是年龄,c 是身高。
你可以把 select * from table where b = 18 and c = 170 拆开成 select * from table where a = '男' and b = 18 and c = 170 union all select * from table where a = '女' and b = 18 and c = 170
这样就可以走索引了,很有可能比不走索引要快。
数据库可以帮你这样优化,但到底会不会优化呢? in most cases the planner would prefer a sequential table scan.

https://www.postgresql.org/docs/12/indexes-multicolumn.html
1424659514
2020-03-24 18:22:11 +08:00
@cxshun 老哥牛批
mitoop
2020-03-25 00:18:19 +08:00
@cxshun 正解 同意 @vindurriel 的说法 老老实实建立好索引 即使用了覆盖索引 还是会 type=index 比 type=all 好那么一点 如果就 abc 三个字段 和 type=all 几乎一样了
xiaowangge
2020-03-28 19:46:28 +08:00
应该换个更详细的问题,表结格和 explain 分析图:

参考这个:

mysql 索引最左匹配原则的理解
https://www.zhihu.com/question/36996520
54qyc
272 天前
@CRVV 但是这适用于 mysql 吗?
54qyc
271 天前
@dovme type = index 扫描索引。extra= using index 不用回表因为 abc 二级索引有全部数据。extra= using where 用 where 子句过滤扫描的行。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/655560

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX