MySQL(56)什么是复合索引?

复合索引(Composite Index),也称为多列索引,是在数据库表的多列上创建的索引。它可以提高涉及多个列的查询性能,通过组合多个列的值来索引数据。复合索引特别适用于需要同时过滤多列的查询。

复合索引的优点

  1. 提高多列查询的性能:复合索引能够优化涉及多个列的查询。
  2. 支持多种查询模式:可以支持前缀列的多种组合查询。
  3. 减少索引的数量:相比于为每一列创建单独的索引,复合索引可以减少索引的数量和维护开销。

1. 示例表结构

假设有一个名为 employees 的表,用于存储员工信息:

sql 复制代码
CREATE TABLE employees (
    emp_id INT AUTO_INCREMENT PRIMARY KEY,
    emp_name VARCHAR(100),
    department_id INT,
    salary DECIMAL(10, 2),
    hire_date DATE
);

2. 创建复合索引

假设我们经常需要按 department_idsalary 查询员工数据:

sql 复制代码
SELECT emp_name, salary FROM employees WHERE department_id = 2 AND salary > 50000;

可以为 department_idsalary 列创建复合索引:

sql 复制代码
CREATE INDEX idx_dept_salary ON employees(department_id, salary);

3. 使用 EXPLAIN 验证复合索引

使用 EXPLAIN 分析查询的执行计划,验证是否使用了复合索引:

sql 复制代码
EXPLAIN SELECT emp_name, salary FROM employees WHERE department_id = 2 AND salary > 50000;

假设 EXPLAIN 的输出如下:

plaintext 复制代码
+----+-------------+----------+------------+-------+----------------+-------------+---------+------+------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys  | key         | key_len | ref  | rows | filtered | Extra       |
+----+-------------+----------+------------+-------+----------------+-------------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employees| NULL       | ref   | idx_dept_salary| idx_dept_salary| 8   | const| 100  |   100.00 | Using where |
+----+-------------+----------+------------+-------+----------------+-------------+---------+------+------+----------+-------------+

key 列中显示 idx_dept_salary 表示查询使用了复合索引。

4. 复合索引的使用规则

复合索引的顺序非常重要,因为查询优化器会根据索引列的顺序来利用索引。我们需要理解以下几种情况:

示例查询1:完全匹配索引的前缀

查询使用索引的前缀列:

sql 复制代码
SELECT emp_name, salary FROM employees WHERE department_id = 2;

这查询只使用了复合索引的第一个列 department_id,仍然可以利用复合索引。

示例查询2:匹配索引的所有列

查询使用了所有的索引列:

sql 复制代码
SELECT emp_name, salary FROM employees WHERE department_id = 2 AND salary > 50000;

这种查询可以完全利用复合索引。

示例查询3:不匹配索引的前缀

查询不使用索引的前缀列:

sql 复制代码
SELECT emp_name, salary FROM employees WHERE salary > 50000;

这种查询无法利用复合索引,因为 department_id 是索引的前缀,但查询中并未使用。

5. 复合索引的局限性

尽管复合索引可以显著提高查询性能,但它们也有一些局限性:

  1. 索引顺序重要:复合索引的列顺序会影响查询的性能,选择不当可能无法充分利用索引。
  2. 增加写操作的开销:插入、更新、删除操作需要维护更多的索引,增加了写操作的开销。
  3. 占用更多存储空间:复合索引会占用更多的磁盘空间。

6. 复合索引的最佳实践

  1. 合理选择列顺序:将选择性高的列放在复合索引的前面,以最大化查询性能。
  2. 考虑查询模式:根据常见的查询模式设计复合索引,以确保查询能够利用索引。
  3. 监控和优化 :使用 EXPLAIN 分析查询性能,确保查询优化器选择适当的索引。

7. 复合索引的高级示例

假设我们有一个更复杂的查询需求,涉及多个列的组合:

sql 复制代码
SELECT emp_name, salary FROM employees WHERE department_id = 2 AND salary > 50000 AND hire_date > '2023-01-01';

可以为 department_idsalaryhire_date 列创建复合索引:

sql 复制代码
CREATE INDEX idx_dept_salary_date ON employees(department_id, salary, hire_date);

使用 EXPLAIN 分析这个查询的执行计划:

sql 复制代码
EXPLAIN SELECT emp_name, salary FROM employees WHERE department_id = 2 AND salary > 50000 AND hire_date > '2023-01-01';

假设 EXPLAIN 的输出如下:

plaintext 复制代码
+----+-------------+----------+------------+-------+-------------------+-------------------+---------+-------+------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys     | key               | key_len | ref   | rows | filtered | Extra       |
+----+-------------+----------+------------+-------+-------------------+-------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employees| NULL       | ref   | idx_dept_salary_date | idx_dept_salary_date | 12    | const | 100  |   100.00 | Using where |
+----+-------------+----------+------------+-------+-------------------+-------------------+---------+-------+------+----------+-------------+

key 列中显示 idx_dept_salary_date 表示查询使用了复合索引,优化了查询性能。

小结

复合索引是数据库优化中非常强大的工具,特别适用于多列查询和复杂查询模式。通过合理设计和使用复合索引,可以显著提高查询性能,减少I/O操作,提升数据库系统的整体效率。然而,复合索引的设计需要仔细考虑列的顺序和查询模式,以确保索引能够充分发挥作用。在实际应用中,通过定期监控和优化,可以最大化复合索引的优势,确保数据库的高效运行。

相关推荐
绝无仅有10 小时前
猿辅导Java面试真实经历与深度总结(二)
后端·面试·github
绝无仅有10 小时前
猿辅导Java面试真实经历与深度总结(一)
后端·面试·github
Victor35611 小时前
Redis(76)Redis作为缓存的常见使用场景有哪些?
后端
Victor35611 小时前
Redis(77)Redis缓存的优点和缺点是什么?
后端
摇滚侠14 小时前
Spring Boot 3零基础教程,WEB 开发 静态资源默认配置 笔记27
spring boot·笔记·后端
天若有情67316 小时前
Java Swing 实战:从零打造经典黄金矿工游戏
java·后端·游戏·黄金矿工·swin
一只叫煤球的猫17 小时前
建了索引还是慢?索引失效原因有哪些?这10个坑你踩了几个
后端·mysql·性能优化
magic3341656318 小时前
Springboot整合MinIO文件服务(windows版本)
windows·spring boot·后端·minio·文件对象存储
开心-开心急了18 小时前
Flask入门教程——李辉 第一、二章关键知识梳理(更新一次)
后端·python·flask
掘金码甲哥19 小时前
调试grpc的哼哈二将,你值得拥有
后端