MySQL 复合索引
简介:在本例中,您将了解MySQL组合索引以及如何使用它来加速查询。
MySQL复合索引简介
复合索引是多列的索引。MySQL允许您创建一个最多包含16列的复合索引。 复合索引也称为多列索引。 查询优化器将复合索引用于测试索引中所有列的查询,或者测试第一列,前两列等的查询。 如果在索引定义中以正确的顺序指定列,则单个复合索引可以在同一个表上加速这些类型的查询。 要在创建表时创建复合索引,请使用以下语句:CREATE TABLE table_name ( c1 data_type PRIMARY KEY, c2 data_type, c3 data_type, c4 data_type, INDEX index_name (c2,c3,c4) );在此语法中,复合索引由三列c2,c3和c4组成。 或者,您可以使用以下
CREATE INDEX
语句将复合索引添加到现有表:
CREATE INDEX index_name ON table_name(c2,c3,c4);请注意,如果您在(c1,c2,c3)上有复合索引,则您将在以下列组合之一上建立索引搜索功能:
(c1) (c1,c2) (c1,c2,c3)例如:
SELECT * FROM table_name WHERE c1 = v1; SELECT * FROM table_name WHERE c1 = v1 AND c2 = v2; SELECT * FROM table_name WHERE c1 = v1 AND c2 = v2 AND c3 = v3;如果列不形成索引的最左前缀,则查询优化器无法使用索引执行查找。例如,以下查询无法使用复合进行查找:
SELECT * FROM table_name WHERE c1 = v1 AND c3 = v3;
MySQL综合索引示例
我们将使用示例数据库中的employees
表进行演示。
+----------------+ | employees | +----------------+ | employeeNumber | | lastName | | firstName | | extension | | email | | officeCode | | reportsTo | | jobTitle | +----------------+ 8 rows in set (0.14 sec)以下语句在
lastName
和firstName
列上创建复合索引:
CREATE INDEX name ON employees(lastName, firstName);首先,
name
索引可用于指定lastName
值的查询中的查找,因为lastName
列是索引的最左前缀。
其次,name
索引可用于指定lastName
和firstName
值组合的值的查询。
name
索引用于在以下的查询查找:
1)查找姓氏为的员工 Patterson
SELECT firstName, lastName, email FROM employees WHERE lastName = 'Patterson';此查询使用名称索引,因为索引的最左边前缀(即
lastName
列)用于查找。
您可以通过EXPLAIN
在查询中添加子句来验证这一点:
EXPLAIN SELECT firstName, lastName, email FROM employees WHERE lastName = 'Patterson';这是输出:
+----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------+ | 1 | SIMPLE | employees | NULL | ref | name | name | 152 | const | 3 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.01 sec)2)查找姓氏
Patterson
和名字的员工Steve
:
SELECT firstName, lastName, email FROM employees WHERE lastName = 'Patterson' AND firstName = 'Steve';在此查询中,两个
lastName
和firstName
列都用于查找,因此,它使用name
索引。
我们来核实一下:
EXPLAIN SELECT firstName, lastName, email FROM employees WHERE lastName = 'Patterson' AND firstName = 'Steve';输出是:
+----+-------------+-----------+------------+------+---------------+------+---------+-------------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+-------------+------+----------+-------+ | 1 | SIMPLE | employees | NULL | ref | name | name | 304 | const,const | 1 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+------+---------+-------------+------+----------+-------+ 1 row in set, 1 warning (0.08 sec)3)查找姓氏
Patterson
和名字是Steve
或的员工Mary
:
SELECT firstName, lastName, email FROM employees WHERE lastName = 'Patterson' AND (firstName = 'Steve' OR firstName = 'Mary');此查询类似于第二个查询,其中两个
lastName
和firstName
列都用于查找。
以下语句验证索引用法:
EXPLAIN SELECT firstName, lastName, email FROM employees WHERE lastName = 'Patterson' AND (firstName = 'Steve' OR firstName = 'Mary');输出是:
+----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | employees | NULL | range | name | name | 304 | NULL | 2 | 100.00 | Using index condition | +----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)查询优化器不能在以下查询中使用
name
索引进行查找,因为只使用了firstName
不是索引最左前缀的列:
SELECT firstName, lastName, email FROM employees WHERE firstName = 'Leslie';类似地,查询优化器不能在以下查询中使用名称索引进行查找,因为
firstName
或者lastName
列用于查找。
SELECT firstName, lastName, email FROM employees WHERE firstName = 'Anthony' OR lastName = 'Steve';在本教程中,您学习了如何使用MySQL组合索引来加速查询。