复合索引(Composite Index),也称为多列索引,是在数据库表的多列上创建的索引。它可以提高涉及多个列的查询性能,通过组合多个列的值来索引数据。复合索引特别适用于需要同时过滤多列的查询。
复合索引的优点
- 提高多列查询的性能:复合索引能够优化涉及多个列的查询。
- 支持多种查询模式:可以支持前缀列的多种组合查询。
- 减少索引的数量:相比于为每一列创建单独的索引,复合索引可以减少索引的数量和维护开销。
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_id
和 salary
查询员工数据:
sql
SELECT emp_name, salary FROM employees WHERE department_id = 2 AND salary > 50000;
可以为 department_id
和 salary
列创建复合索引:
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. 复合索引的局限性
尽管复合索引可以显著提高查询性能,但它们也有一些局限性:
- 索引顺序重要:复合索引的列顺序会影响查询的性能,选择不当可能无法充分利用索引。
- 增加写操作的开销:插入、更新、删除操作需要维护更多的索引,增加了写操作的开销。
- 占用更多存储空间:复合索引会占用更多的磁盘空间。
6. 复合索引的最佳实践
- 合理选择列顺序:将选择性高的列放在复合索引的前面,以最大化查询性能。
- 考虑查询模式:根据常见的查询模式设计复合索引,以确保查询能够利用索引。
- 监控和优化 :使用
EXPLAIN
分析查询性能,确保查询优化器选择适当的索引。
7. 复合索引的高级示例
假设我们有一个更复杂的查询需求,涉及多个列的组合:
sql
SELECT emp_name, salary FROM employees WHERE department_id = 2 AND salary > 50000 AND hire_date > '2023-01-01';
可以为 department_id
、salary
和 hire_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操作,提升数据库系统的整体效率。然而,复合索引的设计需要仔细考虑列的顺序和查询模式,以确保索引能够充分发挥作用。在实际应用中,通过定期监控和优化,可以最大化复合索引的优势,确保数据库的高效运行。