Mysql联合索引生效判断

对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c)。 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。

以下是一些例子:

(1) select * from myTest where a=3 and b=5 and c=4; ---- abc顺序
abc三个索引都在where条件里面用到了,而且都发挥了作用

(2) select * from myTest where c=4 and b=6 and a=3;
where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样

(3) select * from myTest where a=3 and c=7;
a用到索引,b没有用,所以c是没有用到索引效果的(b没有使用到,所以索引达不到 c ,所以c未使用索引)

(4) select * from myTest where a=3 and b>7 and c=3; ---- b范围值,断点,阻塞了c的索引
a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引

(5) select * from myTest where b=3 and c=4; — 联合索引必须按照顺序使用,并且需要全部使用
因为a索引没有使用,所以这里 bc都没有用上索引效果

(6) select * from myTest where a>4 and b=7 and c=9;
a用到了 b没有使用,c没有使用(a用了范围所以,相当于断点,之后的b,c都没有用到索引)

(7) select * from myTest where a=3 order by b;
a用到了索引,b在结果排序中也用到了索引的效果,a下面任意一段的b是排好序的

(8) select * from myTest where a=3 order by c;
a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort

(9) select * from mytable where b=3 order by a;
b没有用到索引,排序中a也没有发挥索引效果

以下条件会导致索引失效:
1.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
2.存储引擎不能使用索引范围条件右边的列(例如 只用到b , c)
3.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select ***
4.mysql在使用不等于(!=或者<>)的时候**无法使用索引会导致全表扫描

5.is null,is not null也无法使用索引

6.ike以通配符开头(’%abc…’)mysql索引失效会变成全表扫描的操作。问题:解决like‘%字符串%’时索引不被使用的方法

7.字符串不加单引号索引失效

建议:

对于单键索引,尽量选择针对当前query过滤性更好的索引

在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。

. 在选择组合索引的时候,尽量选择可以能够包含当前query中的where子句中更多字段的索引

. 在选择组合索引的时候,尽量选择可以能够包含当前query中的where子句中更多字段的索引

尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的
 

原文转载至:https://blog.youkuaiyun.com/qq_42630887/article/details/97113323

 

<think>嗯,用户问的是MySQL联合索引中有一个字段可能为空,是否可以作为联合索引字段。首先,我需要确认联合索引是否允许包含可为空的字段。根据之前的知识,MySQL中的索引是可以包含NULL值的,但具体到联合索引中的情况可能会有不同的表现。 然后,我需要回忆一下联合索引的工作原理。联合索引是按照索引字段的顺序来存储和排序的,如果其中一个字段为NULL,那么该记录在索引中的位置可能会受到影响。例如,假设有一个联合索引(a, b),如果a字段不为空,而b字段可以为空,那么在索引中,a的值会被存储,而b为NULL的记录可能会被放在索引的某个位置,具体取决于MySQL的处理方式。 接下来,需要考虑使用含有NULL值的字段作为联合索引的一部分时,查询优化器能否有效利用这个索引。比如,当查询条件中包含这个可为空的字段时,索引是否会被使用。例如,如果查询条件是WHERE a = 1 AND b IS NULL,这种情况下索引是否能被正确使用,或者是否需要额外的处理。 另外,还需要考虑索引的存储和效率问题。NULL值在索引中占用的空间和处理方式可能与普通值不同,可能会影响索引的大小和查询性能。例如,如果某个字段有很多NULL值,那么索引中的条目可能会更多,从而增加索引的大小,影响查询速度。 还要想到实际应用中的情况。用户可能在表中设计了一个联合索引,其中某个字段确实存在为NULL的情况,比如订单表中的优惠券字段,可能大部分订单没有使用优惠券,此时该字段为NULL。这时候,联合索引是否能有效支持查询,比如查找某个用户使用特定优惠券的订单,或者未使用优惠券的订单。 然后需要验证之前的观点是否正确。查阅MySQL的官方文档,确认关于索引中允许NULL值的内容。根据文档,MySQL确实允许在索引中包含NULL值,每个索引列可以包含多个NULL值,具体数量取决于存储引擎。例如,InnoDB存储引擎允许每个索引列有多个NULL值。 另外,联合索引中的NULL值处理方式。如果联合索引中的某个字段为NULL,那么该记录仍然会被包含在索引中,但NULL值会被视为最小的值,这可能会影响范围查询时的结果排序和筛选。 还需要考虑唯一索引的情况。如果联合索引是唯一的,那么多个NULL值是否被允许。但用户的问题中没有提到唯一索引,所以可能不需要深入讨论这一点,但可以作为补充信息。 然后,思考用户可能的实际应用场景。用户可能在设计数据库表时遇到了某个字段需要作为联合索引的一部分,但该字段允许为NULL,担心这样会影响索引的效率或可用性。需要给出明确的回答,说明是否可以使用,并给出使用时的注意事项。 总结一下,回答应该包括以下几点:MySQL允许在联合索引中使用可为空的字段;使用时的注意事项,包括查询条件中的IS NULL或IS NOT NULL可能会影响索引使用,以及NULL值对索引存储和排序的影响;最后给出建议,如根据实际查询需求设计索引,或使用COALESCE函数处理NULL值等。 最后,需要确保回答结构清晰,分点说明,并且语言通俗易懂,避免使用过于专业的术语,同时保证准确性。</think>好的,我来逐步解释 MySQL 联合索引中包含「可能为空」字段的相关问题: --- ### 1. **能否使用可能为空的字段作为联合索引?** **答案:可以** MySQL 允许将可为 `NULL` 的字段作为联合索引的一部分,语法和索引创建均无限制。例如: ```sql ALTER TABLE users ADD INDEX idx_name_age (name, age); -- 即使 age 字段可为 NULL ``` --- ### 2. **索引如何存储 NULL 值?** - **存储规则**:MySQL 将 `NULL` 视为「最小值」存储在索引中(类似于 `-infinity`)。 - **联合索引特性**: 如果联合索引是 `(a, b)`,且 `b` 允许为 `NULL`: - `a=1, b=NULL` 的记录会被索引。 - 查询 `WHERE a=1 AND b IS NULL` 时,索引仍可生效。 --- ### 3. **使用时的注意事项** #### (1)查询条件需明确处理 `NULL` - **错误写法**:`WHERE a=1 AND b = NULL`(`NULL` 不能用 `=` 判断) - **正确写法**:`WHERE a=1 AND b IS NULL` #### (2)范围查询可能跳过部分索引 如果联合索引是 `(a, b)`: - 查询 `WHERE a>1`:索引正常生效。 - 查询 `WHERE a=1 AND b>10`:索引生效,但 `b=NULL` 的记录会被过滤(因为 `NULL` 被视为最小值)。 #### (3)索引覆盖需谨慎 若查询需要覆盖索引(避免回表),但字段为 `NULL`: - `SELECT a, b FROM table WHERE a=1`:即使 `b` 为 `NULL`,索引仍能覆盖。 - `SELECT a, b, c FROM table WHERE a=1`:若 `c` 不在索引中,则需回表。 --- ### 4. **实际场景建议** #### (1)高频查询优化 - 如果查询频繁使用 `a=1 AND b IS NULL`,联合索引 `(a, b)` 是合理设计。 - 如果 `b` 的 `NULL` 比例极高(如 80%),建议评估索引效率(大量 `NULL` 可能降低索引筛选性)。 #### (2)替代方案:`COALESCE` 函数 若需将 `NULL` 转换为具体值参与索引: ```sql ALTER TABLE users ADD INDEX idx_name_age (name, COALESCE(age, 0)); ``` 查询时匹配相同逻辑: ```sql SELECT * FROM users WHERE name='John' AND COALESCE(age, 0) = 0; ``` --- ### 5. **验证索引使用情况** 通过 `EXPLAIN` 确认索引是否生效: ```sql EXPLAIN SELECT * FROM users WHERE name='John' AND age IS NULL; ``` 观察 `key` 列是否显示 `idx_name_age`。 --- ### 总结 - **允许使用**:可为 `NULL` 的字段可以作为联合索引的一部分。 - **注意查询条件**:正确处理 `IS NULL` 或 `IS NOT NULL`。 - **权衡索引效率**:根据数据分布和查询模式决定是否使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值