Mysql联合索引的生效方式,最左前缀匹配

1. 我们先创建表

create table test( a int , b int, c int, d int, key index_abc(a,b,c) )engine=InnoDB default charset=utf8;

2. 插入一些数据

DROP PROCEDURE IF EXISTS proc_initData;
DELIMITER $
CREATE PROCEDURE proc_initData()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<=10000 DO
    INSERT INTO test(a,b,c,d) VALUES(i,i,i,i);
    SET i = i+1;
END WHILE;
END $
CALL proc_initData();

3. 可以看到。我们建表的时候是设置了abc三列的组合索引。所以当我们

explain select * from test where a<10 ;
explain select * from test where a<10 and b <10;
explain select * from test where a<10 and b <10 and c<10;

可以看到数据库都是走了索引的

而且我们执行

explain select * from test where b<10 and a<10;

也是会走索引的。因为数据库优化器帮我们进行了优化。其实真正执行时会按索引顺序a<10 and b<10这种来执行的。

但是如果时

explain select * from test where  b<10 and c <10

这时候为什么没有走索引了呢?最左前缀匹配原则是假设我们设置(name,age,id)顺序为索引时。name是建立索引树的第一个比较因子,所以要现有name,才知道搜索方向。

结论:

1. 联合索引abc,可以匹配a,ab,abc的查询

2. ab,abc的查询where顺序不影响,因为mysql优化器会帮我们进行顺序优化

3. where bc,ac的时候,不走索引,必须从左到右匹配

<think>嗯,用户想了解最左前缀匹配在LIKE语句中的用法和优化,以及相关的索引使用场景。首先,我需要回忆一下最左前缀匹配的概念。根据引用[1],联合索引是按照最左前缀匹配的,也就是说,查询条件必须包含索引的最左边的列,才能利用索引。比如有索引(a,b,c),查询条件必须包含a,才能用上这个索引。 然后,用户提到了LIKE语句。引用[3]里有一个例子,name like 'L%',这里name是联合索引的第一个列,所以可以有效地使用索引。这说明当LIKE的条件是前缀匹配时,也就是通配符在右边,比如'L%',这时候索引是有效的。但如果通配符在左边或者两边,比如'%L'或'%L%',这时候索引可能不会被使用,因为无法利用索引的有序性。 接下来,我需要考虑如何优化LIKE查询。根据引用[4],MySQL的查询优化器会调整查询顺序以利用索引,但前提是查询条件符合最左前缀原则。所以,如果用户有一个联合索引(name, age),即使查询中有其他条件,只要name使用了前缀匹配的LIKE,优化器可能仍然会使用索引。 另外,用户可能想知道具体的例子和应用场景。比如,当使用LIKE 'L%'时,索引有效,而其他情况可能无效。同时,可能需要提到覆盖索引,即如果查询的列都在索引中,可以避免回表,提高效率。 还要注意,如果索引列是字符串类型,字符集和排序规则可能会影响索引的使用。比如,使用前缀索引或者不同的collation可能导致不同的效果。 然后,用户的问题可能还涉及如何设计索引来优化LIKE查询。比如,是否需要将使用LIKE的列放在联合索引的最左边,或者是否需要单独建立索引。 最后,结合引用[2]中的索引优化和查询优化的关系,应该强调在编写SQL时,尽量让LIKE条件符合最左前缀,并且结合索引设计,以达到最佳性能。</think>### 最左前缀匹配在LIKE语句中的用法与优化 #### 1. 最左前缀匹配与LIKE语句的关系 最左前缀匹配原则要求**查询条件必须从联合索引的最左侧列开始**,且连续使用索引中的列(或范围查询前的列)。对于LIKE语句,该原则的适用性取决于通配符`%`的位置: - **可优化场景**:`LIKE '前缀%'`(通配符仅在右侧)可以利用索引,例如联合索引`(name, age)`的查询`WHERE name LIKE 'L%'`[^3]。 - **不可优化场景**:`LIKE '%后缀'`或`LIKE '%中缀%'`(通配符在左侧或两侧)无法使用索引,因为破坏了索引的有序性。 #### 2. 优化方法与使用场景 | 场景 | 索引设计 | 查询示例 | 是否生效 | 原因 | |---------------------|-----------------------|----------------------------|----------|--------------------------| | 前缀匹配 | `INDEX(name)` | `WHERE name LIKE '张%'` | ✅ | 符合最左前缀有序性 | | 后缀/全模糊匹配 | 无有效单列索引 | `WHERE name LIKE '%伟'` | ❌ | 索引无法逆向扫描 | | 联合索引中的前缀匹配| `INDEX(name, age)` | `WHERE name LIKE 'L%'` | ✅ | 利用索引首列过滤 | | 覆盖索引优化 | `INDEX(name, age)` | `SELECT name FROM users` | ✅ | 避免回表查询 | #### 3. 核心优化策略 1. **固定前缀长度** 对长文本字段(如地址),可创建**前缀索引**: ```sql ALTER TABLE users ADD INDEX idx_address_prefix (address(10)); ``` 通过截取前N个字符建立索引,需平衡查询精度和存储空间。 2. **联合索引设计** 若查询包含其他条件,将LIKE字段作为联合索引首列: ```sql -- 有效场景 SELECT * FROM employees WHERE name LIKE '王%' AND department = '技术部'; -- 索引设计 ALTER TABLE employees ADD INDEX idx_name_dept (name, department); ``` 3. **避免无效通配符** ```sql -- 优化前(全模糊查询) SELECT * FROM products WHERE description LIKE '%防水%'; -- 优化后(通过全文索引实现) ALTER TABLE products ADD FULLTEXT INDEX idx_desc (description); SELECT * FROM products WHERE MATCH(description) AGAINST('防水'); ``` #### 4. 性能影响示例 假设表`users`有100万条记录: - **有效索引**(`LIKE 'A%'`) 通过B+树快速定位到以A开头的叶子节点,时间复杂度为$O(\log n)$。 - **无效索引**(`LIKE '%A'`) 需要全表扫描,时间复杂度为$O(n)$,性能差距可达数百倍。 #### 5. 特殊场景说明 - **字符集影响**:使用`utf8mb4`字符集时,索引长度限制为191字符(InnoDB),需注意前缀截断。 - **COLLATION设置**:`WHERE name LIKE 'a%'`在`utf8mb4_bin`区分大小写,而在`utf8mb4_general_ci`不区分。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值