mysql索引-LMLPHP

MySQL索引是一种数据结构,用于快速访问数据库表中的数据。索引可以提高数据库的查询性能,减少查询所需的时间,因为它们允许MySQL在查询期间快速定位表中特定的行,而不必扫描整个表。

MySQL支持多种类型的索引,包括:

B-Tree索引:B-Tree是MySQL中最常用的索引类型,它可以用于所有数据类型,包括字符串和数值类型。B-Tree索引对于等值查询和范围查询非常有效。

哈希索引:哈希索引可以快速定位特定的行,但只支持等值查询,不支持范围查询。

全文索引:全文索引可以用于对文本数据进行高效的全文搜索,例如文章、博客和评论等。

空间索引:空间索引可以用于存储和查询具有空间数据的表,例如地图和地理位置数据。

在MySQL中,可以为表中的一个或多个列创建索引。索引可以在创建表时定义,也可以在表已经创建后添加。但是,对于大型的表,应该仔细考虑哪些列需要索引,因为索引可能会导致写操作的性能下降,因为每次插入、更新或删除操作都必须更新索引。

**

什么时候索引会失效?

**
违反最左前缀原则
拿我们文章开始创建的联合索引为例,该联合索引的B+树数据页内的记录首先按照name字段进行排序,name字段相同的情况下,再按照phone字段进行排序。

所以,如果我们直接使用phone字段进行搜索,无法利用索引的顺序性。

EXPLAIN SELECT * FROM user_innodb WHERE phone = “13203398311”;
image-20220315165212944

EXPLAIN可以查看搜索语句的执行计划,其中,possible_keys列表示在当前查询中,可能用到的索引有哪一些;key列表示实际用到的索引有哪一些。
但是一旦加上name的搜索条件,就会使用到联合索引,而且不需要在意name在WHERE子句中的位置,因为查询优化器会帮我们优化。

EXPLAIN SELECT * FROM user_innodb WHERE phone = “13203398311” AND name = ‘蝉沐风’;
image-20220315165908904

使用反向查询(!=, <>,NOT LIKE)
MySQL在使用反向查询(!=, <>, NOT LIKE)的时候无法使用索引,会导致全表扫描,覆盖索引除外。

EXPLAIN SELECT * FROM user_innodb WHERE name != ‘蝉沐风’;
image-20220315190829963

LIKE以通配符开头
当使用name LIKE '%沐风’或者name LIKE '%沐%'这两种方式都会使索引失效,因为联合索引的B+树数据页内的记录首先按照name字段进行排序,这两种搜索方式不在意name字段的开头是什么,自然就无法使用索引,只能通过全表扫描的方式进行查询。

EXPLAIN SELECT * FROM user_innodb WHERE name LIKE ‘%沐风’;
image-20220315202339837

但是使用通配符结尾就没有问题

EXPLAIN SELECT * FROM user_innodb WHERE name LIKE ‘蝉沐%’;
image-20220315202531736

对索引列做任何操作
如果不是单纯使用索引列,而是对索引列做了其他操作,例如数值计算、使用函数、(手动或自动)类型转换等操作,会导致索引失效。

使用函数
EXPLAIN SELECT * FROM user_innodb WHERE LEFT(name,3) = ‘蝉沐风’;
image-20220315203446591

MySQL8.0新增了函数索引的功能,我们可以给函数作用之后的结果创建索引,使用以下语句

ALTER TABLE user_innodb ADD KEY IDX_NAME_LEFT ((left(name,3)));
再次执行EXPLAIN语句,此时索引生效

image-20220315204529598

使用表达式
EXPLAIN SELECT * FROM user_innodb WHERE id + 1 = 1100000;
image-20220315205336452

换一种方式,单独使用id,就能高效使用索引:

EXPLAIN SELECT * FROM user_innodb WHERE id = 1100000 - 1;
image-20220315205618100

使用类型转换
例1

user_innodb中的phone字段为varchar类型,实验之前我们先给phone字段创建个索引

ALTER TABLE user_innodb ADD INDEX IDX_PHONE (phone);
随便搜索一个存在的手机号,看一下索引是否成功

EXPLAIN SELECT * FROM user_innodb WHERE phone = ‘13203398311’;
image-20220315211631637

可以看到能使用到索引,现在我们稍微修改一下,把phone = '13203398311’修改为phone = 13203398311,这意味着我们将字符串的搜索条件改成了整形的搜索条件,再看一下还会不会使用到索引:

EXPLAIN SELECT * FROM user_innodb WHERE phone = 13203398311;
image-20220315212929411

显示索引失效。

例2

我们再看一个例子,主键id类型是bigint,但是在搜索条件中我估计使用字符串类型:

EXPLAIN SELECT * FROM user_innodb WHERE id = ‘1099999’;
image-20220315213426349

04-27 09:33