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

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

MySQL中On duplicate key update的实现示例

《MySQL中Onduplicatekeyupdate的实现示例》ONDUPLICATEKEYUPDATE是一种MySQL的语法,它在插入新数据时,如果遇到唯一键冲突,则会执行更新操作,而不是抛... 目录1/ ON DUPLICATE KEY UPDATE的简介2/ ON DUPLICATE KEY UP

MySQL分库分表的实践示例

《MySQL分库分表的实践示例》MySQL分库分表适用于数据量大或并发压力高的场景,核心技术包括水平/垂直分片和分库,需应对分布式事务、跨库查询等挑战,通过中间件和解决方案实现,最佳实践为合理策略、备... 目录一、分库分表的触发条件1.1 数据量阈值1.2 并发压力二、分库分表的核心技术模块2.1 水平分

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja