SQL 结构定义:索引 INDEX

当数据库表的数据量不断增长时,查询效率会变慢,以前查询数据 100 毫秒内就返回,现在可能需要几秒钟。

索引作为数据库优化查询的核心手段之一,能够大幅提升数据检索速度,就像书籍的目录一样,帮助数据库快速定位目标数据,避免全表扫描带来的性能损耗。

本文将从索引的基础概念出发,详细讲解SQL索引的分类、创建方法、管理技巧。

 

索引的概念与作用

什么是索引?

索引是数据库系统在表的基础上构建的一种有序数据结构,它将表中一个或多个列的值(索引键)与对应数据行的物理存储地址关联起来。当执行查询语句时,数据库引擎可以通过索引快速查找符合条件的索引键,进而定位到具体的数据行,而非遍历表中的所有记录。

注意:索引并非 “万能优化工具”,它能提升查询效率,但会增加数据插入、更新、删除(DML操作)的开销 —— 因为修改数据时,不仅要更新表数据,还需同步维护索引结构。因此,索引的设计需在查询性能与写入性能之间找到平衡。

索引的作用

(1) 提升查询速度

这是索引最核心的作用。对于百万级、千万级数据量的表,无索引查询可能需要几秒甚至几分钟,而合理的索引能将查询时间缩短至毫秒级。

(2)优化排序操作

当查询语句中包含 ORDER BY、GROUP BY 等排序/分组逻辑时,若索引键与排序/分组字段一致,数据库可直接利用索引的有序性完成排序,避免额外的排序运算。

(3)强制数据唯一性

通过唯一索引(如主键索引),可以约束索引键对应的列值不重复,保障数据的完整性。

 

索引的常见分类

按索引键数量分类

(1)单列索引

指仅基于表中的一个列创建的索引,适用于查询条件中仅涉及该列的场景。例如,为用户表(user)的 “手机号” 列(phone)创建索引,可快速查询指定手机号的用户信息。

(2)复合索引

指基于表中的多个列组合创建的索引,索引键为多个列的值的组合。复合索引遵循 “最左前缀匹配原则” —— 即查询条件需从索引的第一个列开始匹配,否则无法有效利用索引。例如,为订单表(order)的 “用户ID”(user_id)和 “订单时间”(order_time)创建复合索引,查询条件为 “user_id = 1001 AND order_time > '2024-01-01'” 可利用索引,而仅以 “order_time > '2024-01-01'” 为条件则无法利用该索引。

按索引功能分类

(1)普通索引(INDEX)

最基础的索引类型,无任何约束限制,仅用于提升查询效率,一个表可以创建多个普通索引。

(2)唯一索引(UNIQUE)

索引键的值必须唯一(允许NULL值,且NULL值可出现多次,因NULL不等于任何值)。用于保障列数据的唯一性,同时提升查询效率。例如,为用户表的 “邮箱” 列创建唯一索引,避免重复注册。

(3)主键索引(PRIMARY KEY)

特殊的唯一索引,用于唯一标识表中的每一行数据。主键索引不允许 NULL 值,一个表只能有一个主键索引。创建主键时,数据库会自动创建对应的主键索引(如 MySQL 的 InnoDB 引擎中,主键索引为聚簇索引)。

按数据结构分类

(1)聚簇索引(Clustered Index)

索引结构与数据行本身存储在一起,索引的叶子节点就是数据行。MySQL 中, InnoDB 引擎的主键索引默认是聚簇索引;若表无主键,则会选择唯一索引作为聚簇索引;若既无主键也无唯一索引,InnoDB 会自动创建一个隐藏的聚簇索引。聚簇索引查询速度极快,因为找到索引就找到了数据。

(2)非聚簇索引(Non-Clustered Index)

索引结构与数据行分开存储,索引的叶子节点存储的是数据行的物理地址(或主键值),而非数据本身。查询时,需先通过非聚簇索引找到地址,再通过地址查找数据(即 “回表查询”)。普通索引、唯一索引(非主键)通常为非聚簇索引。

 

索引的创建与删除

创建索引

索引可以在创建数据表时进行创建,也可以在表创建成功后进行创建。

(1)创建表时创建索引,如下:

-- 示例:创建用户表(users),同步创建主键索引、唯一索引、普通索引
CREATE TABLE `users` (
  `id` INT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `phone` VARCHAR(20) NOT NULL COMMENT '手机号',
  `email` VARCHAR(50) NOT NULL COMMENT '邮箱',
  `username` VARCHAR(30) NOT NULL COMMENT '用户名',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  -- 主键索引(自动创建)
  PRIMARY KEY (`id`),
  -- 唯一索引:保障邮箱唯一
  UNIQUE INDEX idx_user_email (`email`),
  -- 普通索引:提升手机号查询效率
  INDEX idx_user_phone (`phone`),
  -- 复合索引:提升用户ID+创建时间的查询效率
  INDEX idx_user_id_createtime (`id`, `create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

(2)表创建后单独创建索引,语法如下:

CREATE [索引类型] INDEX [索引名] ON [表名] ([列名1], [列名2], ...);

示例:

-- 1. 创建普通索引:为user表的username列创建索引
CREATE INDEX idx_user_username ON `users` (`username`);

-- 2. 创建唯一索引:为user表的phone列创建唯一索引(若已存在普通索引,需先删除)
CREATE UNIQUE INDEX idx_user_phone_unique ON `users` (`phone`);

-- 3. 创建复合索引:为order表的user_id和order_time列创建复合索引
CREATE INDEX idx_order_userid_ordertime ON `orders` (`user_id`, `order_time`);

删除索引

删除索引需要使用 DROP INDEX 语句,语法如下:

DROP INDEX [索引名] ON [表名];

示例:

-- 删除user表的idx_user_username索引
DROP INDEX idx_user_username ON `users`;

-- 删除order表的复合索引idx_order_userid_ordertime
DROP INDEX idx_order_userid_ordertime ON `order`;

 

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号