mysql like %string% 索引失效问题,cluster index, secondary index,covering index意思

本文主要是介绍mysql like %string% 索引失效问题,cluster index, secondary index,covering index意思,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

只有在like 子句是'string%'时,建在该字段的单列索引才会被使用。但实际中LIKE '%string%'的查询需求又可能被用到,该如何做?

这时可以用覆盖索引。就是新建一个联合索引,包含了select语句中要查询的所有字段(select语句要查询的字段不能超出联合索引包含的字段哦,除了主键id),这个时候用explain看执行计划,type是index,不是all了。也就是避免了全表扫描,但是还是会进行全索引扫描,尽管如此,性能还是会好一些。

比如下边的例子

mysql> desc employees;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| employee_id    | int(6)       | NO   | PRI | NULL    | auto_increment |
| first_name     | varchar(20)  | YES  |     | NULL    |                |
| last_name      | varchar(25)  | YES  |     | NULL    |                |
| email          | varchar(25)  | YES  |     | NULL    |                |
| phone_number   | varchar(20)  | YES  |     | NULL    |                |
| job_id         | varchar(10)  | NO   |     | NULL    |                |
| salary         | double(10,2) | YES  |     | NULL    |                |
| commission_pct | double(4,2)  | YES  |     | NULL    |                |
| manager_id     | int(6)       | YES  |     | NULL    |                |
| department_id  | int(4)       | YES  | MUL | NULL    |                |
| hiredate       | datetime     | YES  |     | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+mysql> SELECT * FROM employees limit 10;
+-------------+------------+-----------+----------+--------------+------------+----------+----------------+------------+---------------+---------------------+
| employee_id | first_name | last_name | email    | phone_number | job_id     | salary   | commission_pct | manager_id | department_id | hiredate            |
+-------------+------------+-----------+----------+--------------+------------+----------+----------------+------------+---------------+---------------------+
|         100 | Steven     | K_ing     | SKING1   | 515.123.4567 | AD_PRES    | 24000.00 |           NULL |       NULL |            90 | 1992-04-03 00:00:00 |
|         101 | Neena      | Kochhar   | NKOCHHAR | 515.123.4568 | AD_VP      | 17000.00 |           NULL |        100 |            90 | 1992-04-03 00:00:00 |
|         102 | Lex        | De Haan   | LDEHAAN  | 515.123.4569 | AD_VP      | 17000.00 |           NULL |        100 |            90 | 1992-04-03 00:00:00 |
|         103 | Alexander  | Hunold    | AHUNOLD  | 590.423.4567 | IT_PROG    |  9000.00 |           NULL |        102 |            60 | 1992-04-03 00:00:00 |
|         104 | Bruce      | Ernst     | BERNST   | 590.423.4568 | IT_PROG    |  6000.00 |           NULL |        103 |            60 | 1992-04-03 00:00:00 |
|         105 | David      | Austin    | DAUSTIN  | 590.423.4569 | IT_PROG    |  4800.00 |           NULL |        103 |            60 | 1998-03-03 00:00:00 |
|         106 | Valli      | Pataballa | VPATABAL | 590.423.4560 | IT_PROG    |  4800.00 |           NULL |        103 |            60 | 1998-03-03 00:00:00 |
|         107 | Diana      | Lorentz   | DLORENTZ | 590.423.5567 | IT_PROG    |  4200.00 |           NULL |        103 |            60 | 1998-03-03 00:00:00 |
|         108 | Nancy      | Greenberg | NGREENBE | 515.124.4569 | FI_MGR     | 12000.00 |           NULL |        101 |           100 | 1998-03-03 00:00:00 |
|         109 | Daniel     | Faviet    | DFAVIET  | 515.124.4169 | FI_ACCOUNT |  9000.00 |           NULL |        108 |           100 | 1998-03-03 00:00:00 |
+-------------+------------+-----------+----------+--------------+------------+----------+----------------+------------+---------------+---------------------+
10 rows in set (0.00 sec)mysql> show index from employees;
+-----------+------------+---------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name            | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+---------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| employees |          0 | PRIMARY             |            1 | employee_id   | A         |         108 |     NULL | NULL   |      | BTREE      |         |               |
| employees |          1 | index_department_id |            1 | department_id | A         |          12 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------+------------+---------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
mysql> explain SELECT * FROM employees WHERE last_name LIKE '%st%';
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL |  108 |    11.11 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

 因为在last_name上没有索引,所以匹配不到索引。下边创建一个联合索引,并且select的字段只包含联合索引包含的字段,顶多再多一个employee_id这个主键索引字段,explain可以看到索引终于有使用上,即使employee_id字段不在联合索引里边。这是因为mysql innodb包含两种索引,cluster index和secondary index。cluster index主要是针对唯一、非空的这种一般用于主键的索引,他底层用到的B+tree,叶子节点会包含执行磁盘具体表记录数据的指针。而普通索引(secondary index),他的叶子节点只包含该条记录的主键id, 然后在普通索引上查到该条记录之后,如果需要差完整一条记录,需要再利用查到的主键id到主键id对应的cluster index上查一遍,这个叫回表。针对我们如下的例子,因为我们只查联合索引的字段,加上主键id三个字段,索引扫描只局限在这两个索引上就ok了,不需要对磁盘表数据做扫描,所以explain里边type是index。

注意:覆盖索引(covering index)是指select语句匹配到的索引是这样的 - select所有select字段都包含在了索引里边,顶多再加一个主键id,这时候,通过索引本身就可以查到所有数据,不需要再对表扫描了,这个时候,这个索引就叫覆盖索引,它可以是包含一个列的索引,也可以是联合索引。

mysql> create index idx_last_name on employees(last_name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> explain SELECT * FROM employees WHERE last_name LIKE '%st%';
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL |  108 |    11.11 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)mysql> explain SELECT * FROM employees WHERE last_name LIKE 'st%';
+----+-------------+-----------+------------+-------+---------------+---------------+---------+------+------+----------+-----------------------+
| id | select_type | table     | partitions | type  | possible_keys | key           | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-----------+------------+-------+---------------+---------------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | employees | NULL       | range | idx_last_name | idx_last_name | 53      | NULL |    1 |   100.00 | Using index condition |
+----+-------------+-----------+------------+-------+---------------+---------------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)mysql> create index idx_last_name_first_name on employees(last_name,first_name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> select employee_id, first_name, last_name from employees WHERE last_name LIKE '%st%';
+-------------+------------+------------+
| employee_id | first_name | last_name  |
+-------------+------------+------------+
|         105 | David      | Austin     |
|         151 | David      | Bernstein  |
|         104 | Bruce      | Ernst      |
|         201 | Michael    | Hartstein  |
|         177 | Jack       | Livingston |
|         138 | Stephen    | Stiles     |
+-------------+------------+------------+
6 rows in set (0.00 sec)mysql> explain select employee_id, first_name, last_name from employees WHERE last_name LIKE '%st%';
+----+-------------+-----------+------------+-------+---------------+--------------------------+---------+------+------+----------+--------------------------+
| id | select_type | table     | partitions | type  | possible_keys | key                      | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+-----------+------------+-------+---------------+--------------------------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | employees | NULL       | index | NULL          | idx_last_name_first_name | 96      | NULL |  108 |    11.11 | Using where; Using index |
+----+-------------+-----------+------------+-------+---------------+--------------------------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

这篇关于mysql like %string% 索引失效问题,cluster index, secondary index,covering index意思的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/905770

相关文章

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

解决RocketMQ的幂等性问题

《解决RocketMQ的幂等性问题》重复消费因调用链路长、消息发送超时或消费者故障导致,通过生产者消息查询、Redis缓存及消费者唯一主键可以确保幂等性,避免重复处理,本文主要介绍了解决RocketM... 目录造成重复消费的原因解决方法生产者端消费者端代码实现造成重复消费的原因当系统的调用链路比较长的时

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

解密SQL查询语句执行的过程

《解密SQL查询语句执行的过程》文章讲解了SQL语句的执行流程,涵盖解析、优化、执行三个核心阶段,并介绍执行计划查看方法EXPLAIN,同时提出性能优化技巧如合理使用索引、避免SELECT*、JOIN... 目录1. SQL语句的基本结构2. SQL语句的执行过程3. SQL语句的执行计划4. 常见的性能优

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

kkFileView启动报错:报错2003端口占用的问题及解决

《kkFileView启动报错:报错2003端口占用的问题及解决》kkFileView启动报错因office组件2003端口未关闭,解决:查杀占用端口的进程,终止Java进程,使用shutdown.s... 目录原因解决总结kkFileViewjavascript启动报错启动office组件失败,请检查of

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作