MySQL 索引

2023-09-14 14:26:38


数据库索引是MySQL中提高查询性能和数据检索速度的关键工具之一。本文将介绍MySQL索引的基本概念,如何创建索引,以及如何使用索引来优化数据库查询。

1.什么是索引?

数据库索引是一种数据结构,用于加速数据库查询操作。它是一个单独的数据结构,存储了特定列的值以及指向包含这些值的数据行的指针。通过使用索引,数据库可以更快速地定位和检索数据,而不必扫描整个表。

2.为什么使用索引?

提高 SELECT 操作性能的最佳方法是在查询中测试的一个或多个列上创建索引。索引条目的作用就像指向表行的指针,允许查询快速确定哪些行与 WHERE 子句中的条件匹配,并检索这些行的其他列值。所有 MySQL 数据类型都可以建立索引。

尽管为查询中可能使用的每个列创建索引可能很诱人,但不必要的索引会浪费空间,并且会浪费 MySQL 确定要使用哪些索引的时间。 索引还会增加插入、更新和删除的成本,因为每个索引都必须更新。 您必须找到适当的平衡点,以使用最佳索引集实现快速查询。

3.创建索引

MySQL InnoDB 自动为主键字段创建一个索引(PRIMARY),这个索引被称为聚集索引(Clustered Index)。

聚集索引包含了表中的数据,也就是说表按照索引的顺序进行组织存储。因此,通过主键进行查找时性能最好。

除此之外,我们可以通过CREATE INDEX语句或者相应的ALTER TABLE ADD INDEX语句创建其他索引,也就是二级索引(Secondary Index)或者非聚集索引(Non-clustered Index)。

CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (key_part,...)
    [index_option]
    [algorithm_option | lock_option] ...

key_part: {col_name [(length)] | (expr)} [ASC | DESC]

index_option: {
    KEY_BLOCK_SIZE [=] value
  | index_type
  | WITH PARSER parser_name
  | COMMENT 'string'
  | {VISIBLE | INVISIBLE}
  | ENGINE_ATTRIBUTE [=] 'string'
  | SECONDARY_ENGINE_ATTRIBUTE [=] 'string'
}

index_type:
    USING {BTREE | HASH}

algorithm_option:
    ALGORITHM [=] {DEFAULT | INPLACE | COPY}

lock_option:
    LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}

ALTER TABLE table_name ADD {INDEX | KEY} [index_name]
        [index_type] (key_part,...) [index_option] ...

UNIQUE(可选):用于创建唯一索引。唯一索引确保表中的索引列不包含重复的值。

FULLTEXT(可选):用于创建全文索引。全文索引用于全文搜索,通常用于文本搜索。

SPATIAL(可选):用于创建空间索引。空间索引用于处理地理空间数据。

index_name:这是要创建的索引的名称。索引名称必须在表内唯一。

index_type(可选):这是索引的类型。MySQL支持不同类型的索引,如 BTREE 和 HASH。通常情况下,你不需要指定索引类型,MySQL会自动选择适当的类型。

tbl_name:这是要在其上创建索引的表的名称。

(key_part,…):这是指定要包含在索引中的列或列的列表。你可以在索引中指定一个或多个列。如果指定了多个字段,表示创建多列索引或者复合索引。ASC(默认值)表示索引值按照升序进行存储,DESC 表示索引值按照降序进行存储。

index_option(可选):这是一组可选的索引选项,用于指定索引的其他属性,如索引的块大小、全文索引的解析器和注释等。

algorithm_option(可选):用于指定索引创建算法的选项。不同的算法可以影响索引的创建速度和行为。

lock_option(可选):这是用于指定索引创建时的锁定选项。你可以选择不同的锁定级别来控制索引创建的并发性。

下面是一个创建索引的示例。

CREATE TABLE t_index(
   id INT PRIMARY KEY,
   c1 INT,
   c2 INT,
   c3 VARCHAR(50)
);

CREATE INDEX idx_c1 ON t_index(c1);

字段 c1 上创建了一个索引,如果使用该字段作为查询条件,MySQL 执行计划如下:

EXPLAIN SELECT * FROM t_index WHERE c1 = 100;
+----+-------------+---------+------------+------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t_index | NULL       | ref  | idx_c1        | idx_c1 | 5       | const |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+--------+---------+-------+------+----------+-------+

输出结果中的 key = idx_c1 表示通过索引进行查找。

MySQL 允许基于 CHAR、VARCHAR、BINARY 以及 VARBINARY 字段的最前面一部分内容创建索引,同时对于 BLOB 和 TEXT 字段必须指定索引使用的字段长度。这一特性被称为前缀索引(prefix index)。

CREATE INDEX index_name
ON table_name(column_name(length));

对于 CHAR、VARCHAR 以及 TEXT 字段,length 表示字符数量;对于 BINARY、VARBINARY 以及 BLOB字段,length 表示字节数量。

例如基于 c3 的前 20 个字符创建一个前缀索引。

CREATE INDEX idx_c3_prefix ON t_index(c3(20));

MySQL 8.0 增加了函数索引,也就是基于函数或者表达式的值创建索引。例如:

SELECT *
FROM t_index
WHERE UPPER(c3) = 'ABC';

MySQL 8.0 还增加了不可见索引,不可见索引不会被优化器用于优化查询,但是系统仍然会正常维护索引。

CREATE [UNIQUE] INDEX index_name
ON table_name(col1 [ASC | DESC], ...)
VISIBLE | INVISIBLE;

MySQL 8.0 还增加了不可见索引,不可见索引不会被优化器用于优化查询,但是系统仍然会正常进行索引维护。

CREATE [UNIQUE] INDEX index_name
ON table_name(col1 [ASC | DESC], ...)
VISIBLE | INVISIBLE;

默认选项为 VISIBLE,INVISIBLE 表示不可见索引,主键索引不允许设置为不可见。不可见索引可以用于测试删除索引对性能的影响,但不需要真的删除,避免了再次重新创建索引的消耗。

MySQL 8.0 还增加了降序索引,DESC 选项不再被忽略。降序索引可以用于优化降序排序,尤其是多个字段的排序。例如:

CREATE INDEX idx_c1_c2 ON t_index(c1 ASC, c2 DESC);

以上复合索引基于 c1 升序和 c2 降序存储,可以优化以下查询:

SELECT *
FROM t_index
WHERE c1 = 100
ORDER BY c2 DESC;

创建表的时候也可以直接创建索引,主键约束和唯一约束自动创建相应的索引。

创建索引是提高数据库查询性能的重要手段之一。通过创建适当的索引,可以加速数据检索操作,但需要谨慎使用,因为不必要的索引可能会导致性能下降。因此,需要根据具体的查询需求和数据模型来决定是否创建索引以及如何创建索引。

4.查看索引

MySQL 提供了SHOW INDEX语句,用于查看索引信息。

SHOW [EXTENDED] {INDEX | INDEXES | KEYS}
    {FROM | IN} tbl_name
    [{FROM | IN} db_name]
    [WHERE expr]

可选的 EXTENDED 关键字导致输出包含 MySQL 内部使用的、用户无法访问的隐藏索引的信息。

tbl_name FROM db_name 语法的替代方法是 db_name.tbl_name。这两个语句是等价的:

SHOW INDEX FROM mytable FROM mydb;
SHOW INDEX FROM mydb.mytable;

可选的 WHERE子句可以用来使用更一般的条件过滤要返回的索引信息。如果不提供WHERE子句,SHOW INDEX将返回指定表的所有索引信息。比如使用 WHERE 子句来查找具有特定名称的索引:

SHOW INDEX FROM t_index WHERE Key_name = 'idx_c1';

除了上述示例,你还可以根据其他条件来过滤索引信息,例如索引的类型、列名等。

查看表 t_index 的的所有索引。

SHOW INDEX FROM t_index\G
*************************** 1. row ***************************
        Table: t_index
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
*************************** 2. row ***************************
        Table: t_index
   Non_unique: 1
     Key_name: idx_c1
 Seq_in_index: 1
  Column_name: c1
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment:
Index_comment:

Table 是表的名称。
Non_unique 表示是否唯一索引,0 表示非唯一索引。
Key_name 是索引名称,主键索引的名称为 PRIMARY。
Seq_in_index 表示字段在索引中的顺序,从 1 开始。SHOW INDEX 对于复合索引会返回多行结果。
Column_name 是字段名称,对于函数索引显示为 NULL。
Collation 表示索引中该字段的存储顺序,A 表示升序,D 表示降序,NULL 表示未排序。
Cardinality 表示索引中唯一值的估计,运行 ANALYZE TABLE 或者 myisamchk -a(MyISAM 表)命令可以更新统计值。
Sub_part 表示前缀索引的长度,普通索引为 NULL。
Packed 表示索引键的打包方式,NULL 表示未打包。
Null 表示索引是否允许空值,YES 表示允许。
Index_type 是索引方法,包括 BTREE、FULLTEXT、HASH、RTREE 等。
Comment 是关于索引的描述信息,例如索引被禁用时显示为 disabled。
Index_comment 是索引的备注信息,通过 COMMENT 属性添加备注。
Visible 表示索引对于优化器的可见性。
Expression 是函数索引的表达式,普通索引显示为 NULL。

5.修改索引

MySQL 通过ALTER TABLE语句修改索引的属性。

ALTER TABLE table_name ALTER INDEX index_name {VISIBLE | INVISIBLE};

ALTER TABLE table_name RENAME INDEX old_index_name TO new_index_name;

第一个语句用于修改索引的可见性,第二个语句用于修改索引的名称。

以下语句将索引 idx_c1 设置为不可见:

ALTER TABLE t_index ALTER INDEX idx_c1 INVISIBLE;

EXPLAIN
SELECT *
FROM t_index
WHERE c1 = 100;
+----+-------------+---------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |
+----+-------------+---------+------------+------+------------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t_index | NULL       | ref  | idx_c1_c2     | idx_c1_c2 | 5       | const |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+------+------------------+--------+---------+-------+------+----------+-------+

由于 idx_c1 不可见,优化器选择了前文创建的复合索引 idx_c1_c2。

6.删除索引

MySQL 使用DROP INDEX或者ALTER TABLE DROP INDEX语句删除索引。

DROP INDEX index_name ON table_name [algorithm_option | lock_option] ...

ALTER TABLE table_name DROP INDEX index_name [algorithm_option | lock_option] ...

algorithm_option:
    ALGORITHM [=] {DEFAULT | INPLACE | COPY}

lock_option:
    LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}

可选的 ALGORITHM 子句用于指定删除索引的算法。默认情况下,MySQL会选择一个适合的算法来删除索引,通常是一种快速的算法。

  • DEFAULT:由 MySQL 自动选择最合适的算法。
  • INPLACE:尽可能使用就地删除索引的算法,以最小化锁定时间。
  • COPY:创建一个新表,然后复制数据并删除旧表的索引。

可选的 LOCK 子句用于指定删除索引时的锁定选项,控制其他会话对表的访问。锁定选项可以影响其他读写的并发性和等待时间。

  • DEFAULT:由 MySQL 自动选择适当的锁定级别。
  • NONE:不锁定表,允许其他会话并发访问。
  • SHARED:获取共享锁,允许其他会话读取表,但不允许写入。
  • EXCLUSIVE:获取独占锁,阻止其他会话对表进行读取或写入。

NONE、SHARED 和 EXCLUSIVE 锁定选项通常用于 MyISAM 存储引擎。InnoDB 存储引擎通常会使用行级锁定,而不需要显式指定锁定选项。

ALGORITHM 和 LOCK 在 ALTER TABLE 语句中的含义相同。

我们将 t_index 表上的不可见索引 idx_c1 删除:

DROP INDEX idx_c1 ON t_index;

要删除主键,索引名总是 PRIMARY,必须指定为带引号的标识符,因为 PRIMARY 是保留字:

DROP INDEX 'PRIMARY' ON t;

参考文献

8.3 Optimization and Indexes
13.1.15 CREATE INDEX Statement
13.7.7.22 SHOW INDEX Statement
13.1.9 ALTER TABLE Statement
13.1.27 DROP INDEX Statement

更多推荐

绘图系统五:数据产生

文章目录AxisFrame组件源码模式序列化导入数据获取文件信息导入文本导入二进制数据📈一三维绘图系统📈二多图绘制系统📈三坐标轴定制📈四定制绘图风格源码地址Python打造动态绘图系统AxisFrame组件AxisFrame是存放某一维坐标的组件,目前由一个标签,一个下拉选框和一个输入框构成。下拉选框主要目的是

Conditional DETR(ICCV 21)

ConditionalDETR(ICCV21)ConditionalDETRforFastTrainingConvergence加速detr收敛(50epoch收敛)DETR收敛慢的原因DETR训练收敛速度慢,需要500epochsDETR的CrossAttention高度依赖contentembedding(deco

基于矩阵分解算法的智能Steam游戏AI推荐系统——深度学习算法应用(含python、ipynb工程源码)+数据集(一)

目录前言总体设计系统整体结构图系统流程图运行环境Python环境TensorFlow环境PyQt5环境模块实现1.数据预处理相关其它博客工程源代码下载其它资料下载前言本项目采用了矩阵分解算法,用于对玩家已游玩的数据进行深入分析。它的目标是从众多游戏中筛选出最适合该玩家的游戏,以实现一种相对精准的游戏推荐系统。首先,项目

外汇天眼:外汇交易市场与股票交易市场优势对比!

在纽约证券交易所上市的股票大约有2800多只。纳斯达克证券交易所还列出了另外3,300多家股票。您将交易哪一个?有时间留在这么多公司的头上吗?在外汇交易中,有数十种货币交易,但是大多数市场参与者交易了七种主要货币对。难道七个主要货币对都比数千只容易得多吗?这是外汇市场优势之一。另外还有一些其他的优势:1、24小时市场股

【计算机基础】VS断点调试,边学边思考

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】📢:文章若有幸对你有帮助,可点赞👍收藏⭐不迷路🙉📢:内容若有错误,敬请留言📝指正!原创文,转载请注明出处文章目录1、什么是断点?与调试有何关系?

Redis核心数据结构实战与高性能解析

目录一、安装Redis二、Redis线程与高性能2.1Redis是单线程么?2.2Redis读写是单线程为何这么快?2.3Redis如何处理并发操作命令?三、核心数据结构实战3.1字符串常用操作实战SET存入键值对SETNXSETEXMSET批量存入键值对MSETNXDECR原子减1DECRBY原子减INCR原子加1I

【无标题】

易点易动——解决汽车制造企业固定资产管理痛点的智能解决方案在汽车制造行业中,固定资产管理是一项艰巨且繁琐的任务。行政和IT人员经常为管理海量的固定资产而感到焦虑。在实际管理过程中面临着繁琐、低效和容易出错的问题。为了解决这些痛点,易点易动提供了一套智能的固定资产管理和盘点解决方案。一、汽车制造企业固定资产管理的痛点资产

ubuntu 18.04 搭建isaacgym学习环境,并运行legged_gym

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、安装anaconda二、使用conda创建python版本为3.8的虚拟环境三、安装pytorch四、isaac-gym下载安装五、安装legged_gym总结前言系统:ubuntu18.04或20.04python版本3.8一、安装ana

C/C++内存管理相关知识点

1.内存分布C/C++将内存大体上分为四个区域:栈区、堆区、静态区(数据段)、常量区(代码段)。栈区:用来存储函数调用时的临时信息的结构,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。堆区:程序员自己使用malloc或new自己申请出来存的地方。(动态内存分配)静态区:static修饰的数据,全局数据

“新KG”视点 | 漆桂林——知识图谱和大语言模型的共存之道

OpenKG大模型专辑导读知识图谱和大型语言模型都是用来表示和处理知识的手段。大模型补足了理解语言的能力,知识图谱则丰富了表示知识的方式,两者的深度结合必将为人工智能提供更为全面、可靠、可控的知识处理方法。在这一背景下,OpenKG组织新KG视点系列文章——“大模型专辑”,不定期邀请业内专家对知识图谱与大模型的融合之道

企业电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理

功能描述1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看所有的立项信息。主要功能包含:招标立项申请、非招标立项申请、采购立项管理。3、采购项目管理:可对项目采购过程全流程管

热文推荐