MySql--最左匹配原则

本文解析了优快云上一篇关于算法标注的博客,深入讨论了算法标注工程师的工作内容和要求,强调了在不同信息技术领域的专业知识。
<think>我们正在讨论MySQL联合索引的最左匹配原则。根据提供的引用,我们可以总结出以下核心要点: 1. 最左前缀匹配原则是指在使用联合索引时,查询条件必须从索引的最左列开始,并且不能跳过中间的列。 2. 该原则的根本原因在于B+树的数据结构,索引按照定义时的列顺序排序。 3. 在匹配过程中,如果遇到范围查询(如>、<)会停止匹配,而>=、<=、BETWEEN、like前缀匹配则不会停止匹配,但要注意like的通配符在开头会导致索引失效(虽然引用中未直接提及,但这是常识)。 4. 建议将区分度高的字段放在联合索引的左边,以过滤更多数据。 我们将详细解释这些要点,并举例说明。 首先,联合索引(复合索引)是指对表上的多个列进行索引。例如,我们创建一个联合索引: ```sql CREATE INDEX idx_name ON table_name (col1, col2, col3); ``` 这个索引在B+树中的结构是按照col1排序,col1相同再按col2排序,col1和col2都相同再按col3排序。 最左匹配原则意味着: - 查询条件中必须包含col1(即最左列),才能使用该索引。 - 如果查询条件中只有col2和col3,而没有col1,则不会使用该索引(除非有覆盖索引等情况,但这里指索引用于过滤)。 - 如果查询条件有col1和col3,而没有col2,那么索引只会使用col1(因为跳过了col2,col3无法被利用)。 举例说明: - 有效查询(使用整个索引): WHERE col1 = 'a' AND col2 = 'b' AND col3 = 'c' - 有效查询(使用索引的前两列): WHERE col1 = 'a' AND col2 = 'b' - 有效查询(使用索引的第一列): WHERE col1 = 'a' - 无效查询(没有最左列): WHERE col2 = 'b' AND col3 = 'c' -- 不会使用索引 - 部分有效查询(有最左列,但跳过了中间列): WHERE col1 = 'a' AND col3 = 'c' -- 只有col1使用索引,col3不会 对于范围查询: - 当使用范围查询(>、<)时,索引匹配到该列就会停止,后面的列无法使用索引进行查找(但可以使用索引扫描)。例如: WHERE col1 = 'a' AND col2 > 10 AND col3 = 'c' 这里,索引会使用col1和col2(因为col2是范围查询,所以后面的col3无法再使用索引进行精确查找)。 - 但是,对于>=、<=、BETWEEN、like(注意是前缀匹配,即like 'abc%')等,虽然也是范围查询,但不会立即停止匹配,其后的列仍然可能被使用。但要注意,如果like使用了前导通配符(如'%abc')则索引失效。 另外,引用[3]提到:在建立联合索引时,将区分度高的字段放在最左边,这样可以在查询时更有效地过滤数据。 需要注意的是,最左匹配原则不仅适用于等值查询,也适用于范围查询,但要遵循上述规则。 下面我们通过一个具体的例子来演示索引的使用情况: 假设有一个表`user`,有字段`a`, `b`, `c`,并创建联合索引`idx_abc(a,b,c)`。 查询1:`SELECT * FROM user WHERE a=1 AND b=2 AND c=3;` - 索引使用:全部使用,效率最高。 查询2:`SELECT * FROM user WHERE a=1 AND b=2;` - 索引使用:a和b,没有问题。 查询3:`SELECT * FROM user WHERE a=1 AND c=3;` - 索引使用:只有a,因为跳过了b,所以c不会使用索引进行查找(但可能会在a=1的结果中扫描,然后过滤c=3)。 查询4:`SELECT * FROM user WHERE b=2 AND c=3;` - 索引使用:不会使用索引(全表扫描),因为缺少最左列a。 查询5:`SELECT * FROM user WHERE a=1 AND b>2 AND c=3;` - 索引使用:a和b(b是范围查询,所以c无法使用索引进行精确查找)。但注意,在MySQL 5.6之后引入了索引条件下推(ICP),可以在存储引擎层对c进行过滤,但这里c的过滤不是在索引查找阶段,而是在索引扫描阶段。 查询6:`SELECT * FROM user WHERE a=1 AND b like 'abc%' AND c=3;` - 索引使用:a、b和c都可能使用。因为like是前缀匹配,所以MySQL会继续匹配c。 然而,如果查询是`SELECT * FROM user WHERE a=1 AND b like '%abc' AND c=3;`,则b的查询条件无法使用索引(因为通配符开头),所以只有a使用索引。 总结: 最左匹配原则MySQL联合索引的核心规则,理解它有助于设计合理的索引和编写高效的查询语句。 相关问题: 1. 在哪些情况下联合索引的最左匹配原则会失效? 2. 如何选择联合索引的列顺序? 3. 范围查询在联合索引中是如何影响索引使用的? 4. 什么是索引条件下推(ICP)?它如何优化联合索引的查询? </think>### MySQL联合索引最左匹配原则详解 MySQL的**最左前缀匹配原则**是联合索引(复合索引)的核心使用规则,决定了查询是否能高效利用索引。以下是关键要点: #### 一、核心原理 1. **索引结构基础** 联合索引`(col1, col2, col3)`在B+树中的排序逻辑: - 先按`col1`排序 - `col1`相同时按`col2`排序 - `col1`和`col2`相同时按`col3`排序 这种结构要求查询必须**从最左列开始匹配**。 2. **匹配规则** - ✅ **有效匹配**: - `WHERE col1 = ?` - `WHERE col1 = ? AND col2 = ?` - `WHERE col1 = ? AND col2 = ? AND col3 = ?` (索引按定义顺序连续使用) - ❌ **无效匹配**: - `WHERE col2 = ?`(跳过`col1`) - `WHERE col1 = ? AND col3 = ?`(跳过`col2`) (未连续匹配的列无法利用索引)[^1][^3] #### 二、范围查询的特殊性 - **停止匹配的运算符**:`>`、`<` ```sql WHERE col1 = 1 AND col2 > 10 AND col3 = 'A' -- 仅使用col1和col2的索引,col3失效 ``` - **继续匹配的运算符**:`BETWEEN`、`LIKE '前缀%'`、`>=`、`<=` ```sql WHERE col1 = 1 AND col2 LIKE 'Abc%' AND col3 = 'A' -- 索引可匹配所有三列[^3] ``` #### 三、索引设计建议 1. **高频查询列放左侧** `WHERE a=? AND b=?`比`WHERE b=? AND a=?`更高效时,优先创建`(a,b)`索引。 2. **高区分度列优先** 将区分度高的列(如`user_id`)放最左,可快速过滤更多数据[^3]。 3. **避免冗余索引** 已有`(a,b)`索引时,单独创建`(a)`索引是冗余的(最左匹配已覆盖)。 #### 四、示例分析 假设表`users`有联合索引`(last_name, first_name, age)`: ```sql ✅ 有效查询: SELECT * FROM users WHERE last_name = 'Smith' AND first_name = 'John' ✅ 有效查询(范围): SELECT * FROM users WHERE last_name = 'Smith' AND age >= 30 -- age使用索引 ❌ 无效查询: SELECT * FROM users WHERE first_name = 'John' -- 未指定last_name ``` #### 五、底层原因 B+树的**有序嵌套结构**决定了: - 缺失最左列时,无法定位索引的起始搜索点 - 跳过中间列会破坏索引的有序性,导致后续列只能全扫描[^2] --- ### 相关问题 1. 如何验证一个SQL语句是否使用了联合索引? 2. 范围查询导致索引部分失效时,有哪些优化策略? 3. 在哪些场景下联合索引比单列索引更高效? 4. 索引下推(ICP)如何与最左匹配原则协同工作? [^1]: MySQL索引的最左前缀匹配原则详解 [^2]: MySQL 索引最左匹配原则详解 [^3]: MySQL联合索引最左匹配原则使用详解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值