🌈 我是“没事学AI”, 欢迎咨询、交流,共同学习:
👁️ 【关注】我们一起挖 AI 的各种门道,看看它还有多少新奇玩法等着咱们发现
👍 【点赞】为这些有用的 AI 知识鼓鼓掌,让更多人知道学 AI 也能这么轻松
🔖 【收藏】把这些 AI 小技巧存起来,啥时候想练手了,翻出来就能用
💬 【评论】说说你学 AI 时的想法和疑问,让大家的思路碰出更多火花
👉 关注获取更多AI技术干货,点赞/收藏备用,欢迎评论区交流学习心得! 🚀
目录
一、索引的基本概念
索引是数据库中用于提高查询效率的数据结构,通过创建索引可以大幅减少数据扫描的范围,加快查询速度。在关系型数据库中,索引主要分为聚集索引(Clustered Index)和非聚集索引(Non-Clustered Index)两种类型,它们在数据存储方式和应用场景上存在显著差异。
二、聚集索引
2.1 定义与特性
聚集索引决定了表中数据的物理存储顺序,即数据行的物理顺序与索引的逻辑顺序一致。一个表只能有一个聚集索引,因为数据的物理存储顺序只有一种。
聚集索引的特性:
- 数据与索引结构存储在一起
- 叶子节点直接包含数据行
- 插入新数据可能导致数据物理位置移动
- 对范围查询和排序操作效率高
2.2 适用场景
- 经常需要按范围查询的列(如时间范围、数值范围)
- 频繁进行排序的列
- 表中存在明显的查询热点列
2.3 案例实现
以MySQL中的InnoDB存储引擎为例,创建一个包含聚集索引的表:
-- 创建以id为主键(默认创建聚集索引)的用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
created_at DATETIME NOT NULL
);
-- 插入测试数据
INSERT INTO users (username, email, created_at) VALUES
('user1', 'user1@example.com', '2023-01-01 08:00:00'),
('user2', 'user2@example.com', '2023-01-02 09:00:00'),
('user3', 'user3@example.com', '2023-01-03 10:00:00');
-- 按主键范围查询(利用聚集索引,效率高)
SELECT * FROM users WHERE id BETWEEN 1 AND 100;
在InnoDB中,主键默认作为聚集索引,如果表中没有定义主键,InnoDB会选择一个唯一的非空索引代替;如果没有这样的索引,InnoDB会隐式创建一个虚拟的聚集索引。
三、非聚集索引
3.1 定义与特性
非聚集索引的索引结构与数据的物理存储顺序无关,索引的叶子节点存储的是索引键值和指向对应数据行的指针(或主键值)。一个表可以有多个非聚集索引。
非聚集索引的特性:
- 索引结构与数据分开存储
- 叶子节点不直接包含数据行
- 插入新数据不会改变数据的物理存储顺序
- 索引维护成本相对较低
3.2 适用场景
- 经常作为查询条件的非主键列
- 需要频繁进行精确匹配查询的列
- 不适合创建聚集索引但查询频繁的列
3.3 案例实现
继续使用上面的users表,创建非聚集索引并演示查询:
-- 为email列创建非聚集索引
CREATE INDEX idx_users_email ON users(email);
-- 为created_at列创建非聚集索引
CREATE INDEX idx_users_created_at ON users(created_at);
-- 使用email索引进行查询
SELECT * FROM users WHERE email = 'user2@example.com';
-- 使用created_at索引进行查询
SELECT username, email FROM users WHERE created_at > '2023-01-02 00:00:00';
上述查询会先通过非聚集索引找到对应的数据行指针,再通过指针定位到具体的数据行(这个过程称为"书签查找")。
四、聚集索引与非聚集索引的区别
特性 | 聚集索引 | 非聚集索引 |
---|---|---|
数量限制 | 一个表只能有一个 | 一个表可以有多个 |
数据存储 | 索引与数据存储在一起 | 索引与数据分开存储 |
物理顺序 | 决定数据的物理存储顺序 | 不影响数据的物理存储顺序 |
叶子节点 | 包含完整的数据行 | 包含索引键值和数据行指针 |
插入操作 | 可能导致大量数据移动 | 不会导致数据物理移动 |
查询效率 | 范围查询效率高 | 精确匹配查询效率高 |
五、索引使用的最佳实践
5.1 索引设计原则
- 为经常作为查询条件、排序和分组的列创建索引
- 避免在频繁更新的列上创建过多索引
- 对于小表,索引可能不会提高性能,甚至会降低性能
- 考虑索引选择性(区分度),选择性高的列更适合创建索引
5.2 实际应用示例
-- 不恰当的索引使用
CREATE INDEX idx_users_username ON users(username); -- 如果username区分度低,不适合建索引
-- 合理的复合索引创建(遵循最左前缀原则)
CREATE INDEX idx_users_created_at_username ON users(created_at, username);
-- 有效利用复合索引的查询
SELECT * FROM users WHERE created_at > '2023-01-01' AND username LIKE 'user%';
5.3 索引维护
-- 查看索引使用情况
SHOW INDEX FROM users;
-- 分析索引效率
EXPLAIN SELECT * FROM users WHERE email = 'user2@example.com';
-- 删除不再使用的索引
DROP INDEX idx_users_email ON users;