为何MySQL中col_a唯一索引未在query_3查询中被使用?
为什么
query_3无法使用col_a的唯一索引? 你的三个查询逻辑上确实等价,但MySQL的索引使用规则依赖于条件中字段的顺序和匹配逻辑,这直接导致了query_3无法利用col_a的索引,具体原因如下:
1. query_1和query_2能用上col_a索引的原因
- 对于
query_1:SELECT * from t WHERE (col_a,col_b) IN ((x,y),(p,q));
MySQL会优先解析col_a的取值(x和p),因为col_a是唯一索引,数据库可以先通过索引快速定位到col_a=x和col_a=p的行,再在这些行里过滤col_b的匹配条件,所以能高效利用col_a的索引。 - 对于
query_2:SELECT * from t WHERE (col_a = x and col_b = y) OR (col_a = p and col_b = q);
MySQL会将这个OR条件拆分为两个独立的子查询:col_a=x AND col_b=y和col_a=p AND col_b=q。每个子查询都以col_a=值作为前置条件,都能通过col_a的索引定位到目标行,最后合并两个子查询的结果,因此也能用上索引。
2. query_3无法使用col_a索引的原因
query_3的条件是SELECT * from t WHERE (col_b,col_a) IN ((y,x),(q,p));,这里的字段顺序是col_b在前、col_a在后。
MySQL的单列索引(仅col_a)是按照col_a的取值顺序存储数据的,它无法匹配这种以col_b开头的组合条件——数据库没办法从(col_b,col_a)的IN条件中直接提取出col_a的离散取值来利用索引,只能先全表扫描所有行,再逐一校验(col_b,col_a)是否匹配目标组合,自然就用不上col_a的索引了。
解决方案
如果想让query_3也能高效执行,有两种选择:
- 调整条件字段顺序,将
query_3改写成query_1的形式,让col_a作为组合条件的第一个字段; - 创建联合索引
(col_b, col_a),这样(col_b,col_a) IN (...)的条件就能直接匹配这个联合索引,实现快速查询。
内容的提问来源于stack exchange,提问作者Dumb_Pegasus
相关产品推荐
相关产品推荐

