【SQL】索引的使用及EXPLAIN关键字

本文详细介绍了SQL中主键索引、唯一索引、单值索引和复合索引的创建方法,以及如何删除索引。此外,还讲解了EXPLAIN关键字在查询优化中的作用,帮助理解数据库如何处理SQL语句。

索引的类型及创建

1. 主键索引

表中的列设定为主键之后会,数据库会为该列自动建立主SQL键索引
可随表创建时创建主键,如下:

CREATE TABLE 表名 (
	字段1 数据类型 PRIMARY KEY [AUTO_INCREMENT],
	...
);

也可以为已存在的表添加主键(但通常做法是在创建表时创建主键约束) ALTER TABLE 表名 ADD PRIMARY KEY(字段);

2. 唯一索引

列表中的列创建唯一约束时,数据库会为该列自动建立唯一索引
可随表创建时创建唯一索引,如下两种方法

-- 不设置索引名,默认索引名为字段名
CREATE TABLE 表名 (
	字段1 数据类型 UNIQUE,
	...
);

-- 设置索引名
CREATE TABLE 表名 (
	字段1 数据类型,
	...
	UNIQUE  索引名(字段1)
);

也可以为已存在的表设置唯一约束同时建立唯一索引:ALTER TABLE 表名 ADD UNIQUE 索引名(字段名)

3. 单值索引

一个索引中只包含单个列,一张表中可以有多个单值索引
可随表创建时创建单值索引,如下

CREATE TABLE 表名 (
	字段1 数据类型,
	...
	KEY  索引名(字段1)
);

也可以为已存在的表创建单值索引:ALTER TABLE 表名 ADD INDEX 索引名(字段名)

4. 复合索引

一个索引中包含多个列
可随表创建时创建复合索引,如下

CREATE TABLE 表名 (
	字段1 数据类型,
	字段2 数据类型,
	字段3 数据类型,
	...
	KEY  索引名(字段1, 字段2, 字段3, ...)
);

也可以为已存在的表创建复合索引:ALTER TABLE 表名 ADD INDEX 索引名(字段1, 字段2, 字段3, ...)

索引的删除

对于主键索引的删除我们需要删除主键约束 ALTER TABLE 表名 DROP PRIMARY KEY
对于其余索引的删除我们可以执行 DROP INDEX 索引名 ON 表名

注意事项:
当我们删除唯一索引时,对应列的唯一约束也会被删除

EXPLAIN 关键字的使用

用法:EXPLAIN SQL语句
使用 EXPLAIN 关键字可以模拟优化器执行SQL查询语句,从而知道数据库是如何处理SQL语句的。可以用来分析查询语句或是表结构的性能瓶颈。

1.id

查询的序列号,表示查询中执行SELECT子句或操作表的顺序

  • 当id相同时,执行顺序由上至下
  • 当id全都不同时,id值越大越先被执行
  • 当id相同和不相同都存在时,id相同的可以理解为一组,组内从上往下顺序执行,组外id值越大越先执行

2. table

当前操作关于那一张表

  • 临时表会以 derived{id}的形式命名,id取决于子查询语句的id

3. select_type

查询类型,常见类型有SIMPLE,DERIVED,PRIMARY,SUBQUERY

  • SIMPLE:简单的SELECT查询,查询中不包含任何子查询或者UNION
  • DERIVED:在FROM列表中包含的子查询会被标记为 DERIVED。数据库会递归这些子查询,把结果放在临时表里。例如 SELECT * FROM (SELECT t1.content FROM t1) s1; 其中的 SELECT t1.content FROM t1 段便会被标记为DERIVED
  • PRIMARY:查询中包含任何复杂的子部分,最外层的查询被标记为PRIMARY
  • SUBQUERY:在 SELECT或WHERE 列表中包含的子查询

4. type

访问类型排序

  • system:表只有一行记录(等于系统表),这是 CONST 类型的特例,平时基本不会出现
  • const:表示通过索引一次就找到了
  • eq_ref:唯一性索引扫描(字段设置了主键索引或唯一索引)例如:SELECT * FROM t1 JOIN t2 ON t1.id = t2.id 中首先会遍历找到t1中所有数据的id(type为ALL),并将该id分别与t2的id对照,因为t2的id是t2表的主键(每个值都唯一),因此对于t2表的操作会被标记为eq_ref
  • ref:非唯一性索引扫描
  • range:只检索给定范围的行,使用一个索引来选择行。例如 SELECT * FROM t1 WHERE t1.id > 0
  • index:当查询字段均建立过索引时,查询则会只遍历索引树,因为索引文件通常比数据文件小因此index会高效于ALL
  • ALL:将遍历全表以找到匹配的行

注意事项:
效率从好到差依次是:system>const>eq_ref>ref>range>index>all
一般尽可能保证达到range级别,最好能到ref

5. possible_keys

显示可能应用在这张表中的索引(一个或多个)查询涉及到的字段上如果存在索引,则该索引将会被列出来,但不一定被查询实际使用上

使用 `EXPLAIN` 关键字可以分析 SQL 查询的执行计划,帮助了解 MySQL 是如何执行查询的,并判断是否有效利用了索引。以下是详细的使用方法和解析步骤: ### 准备查询语句 首先,选择一个需要分析的 `SELECT` 查询语句,通常带有 `WHERE` 子句,因为这类查询更可能使用索引。例如: ```sql SELECT * FROM users WHERE name = 'John' AND age = 30; ``` ### 添加 EXPLAIN 在查询语句前添加 `EXPLAIN` 关键字,以查看其执行计划: ```sql EXPLAIN SELECT * FROM users WHERE name = 'John' AND age = 30; ``` ### 解析执行计划 执行上述语句后,MySQL 返回的结果集包含多个字段,每个字段提供了关于查询执行的不同信息。以下是关键字段及其含义: - **id**:查询中每个 `SELECT` 的唯一标识符,表示查询的执行顺序。 - **select_type**:查询类型,如 `SIMPLE`(简单查询)、`PRIMARY`(主查询)、`SUBQUERY`(子查询)等。 - **table**:当前查询涉及的表。 - **type**:连接类型,是最重要的字段之一,用于表示查询使用的访问类型。常见的类型包括: - `const`:通过主键或唯一索引直接定位一行数据。 - `eq_ref`:使用主键或唯一索引进行连接。 - `ref`:使用非唯一索引进行查找。 - `range`:使用索引范围扫描,例如 `BETWEEN` 或 `IN`。 - `index`:全索引扫描。 - `ALL`:全表扫描,性能最差。 - **possible_keys**:列出查询可能使用索引。 - **key**:实际使用索引,如果为 `NULL`,表示未使用索引。 - **key_len**:使用索引长度,可用于判断是否使用了复合索引的部分。 - **rows**:MySQL 预计需要扫描的行数,数值越小越好。 - **filtered**:表示存储引擎返回的数据在 Server 层过滤后,满足查询条件的比例(百分比)[^2]。 ### 分析执行结果 - 如果 `type` 列显示为 `const`,表示使用了唯一索引并直接定位到一行数据。 - `eq_ref` 表示使用了主键或唯一索引的全部。 - `ref` 表示使用了非唯一索引或部分索引。 - `range` 表示使用索引范围扫描。 - `index` 或 `ALL` 表示未使用索引,进行了全索引或全表扫描。 - `key` 列为空时,说明没有使用索引。 - `rows` 值越小越好,表示查询效率高。 ### 示例分析 假设执行以下查询: ```sql EXPLAIN SELECT * FROM users WHERE name = 'John'; ``` 返回的结果如下: | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | |----|-------------|-------|------|---------------|------|---------|------|------|----------|-------| | 1 | SIMPLE | users | ref | idx_name | idx_name | 767 | const | 10 | 100.00 | NULL | 从结果可以看出,查询使用了 `idx_name` 索引类型为 `ref`,预计扫描 10 行数据,过滤比例为 100%。 ### 优化建议 - 如果 `type` 是 `ALL`,并且 `rows` 值较大,说明查询效率低下,应考虑为 `WHERE` 子句中涉及的列创建合适的索引。 - 如果 `key` 为 `NULL`,但 `possible_keys` 中有索引,说明 MySQL 未选择使用索引,可能需要优化查询语句或调整索引设计。 - 使用复合索引时,注意索引列的顺序和查询条件的匹配程度。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值