MySQL可以创建组合索引(就是多列索引)。一个索引可以由最多16个字段组成。对于特定的数据类型,你可以只对这个列的前缀添加索引(见章节8.3.5,“Column Indexes”)。
组合索引可以用于校验所有列的查询,也可以用于只校验第一列,或前两列,前三列,以此类推。如果你的指明了索引的前缀列,那一个单一的组合索引就可以加速对同一张表的多种查询。
一个多列索引可以被当成一个有序数组,数组中的记录包含了索引列的值。
如果不用组合索引,你也可以添加一个列,这个列是其它几个列的hash值。如果这个列短,重复性不高,并且上面建立了索引,它可能比一个多列索引更快。在MySQL中,使用这个额外的列很简单:
select * from tbl_name
where hash_col=MD5(concat(val1,val2)) AND col1 = val1 AND col2 = val2;
假设一张表的表结构定义如下:
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name,first_name)
);
索引 name 是一个由last_name和first_name组成的联合索引。这个索引可以被用于有last_name和first_name条件的查询。它也可以被用于只有last_name条件的查询,因为last_name是最左前缀列。因此,索引index可以被用于以下查询:
select * from test where last_name='Widenius';
select * from test where last_name='Jones' and first_name='John';
select * from test where last_name='Jones' and (first_name='John' or first_name='Jon');
select * from test where last_name='Jones' and first_name >='M' and first_name < 'N';
然而,索引name不能用于以下查询:
select * from test where first_name='John';
select * from test where last_name='Widenius' or first_name='Michael';
假设你的select语句如下:
select * from tbl_name where col1=val1 and col2=val2;
如果有一个col1和col2组成的组合索引,就可以直接查找到相关记录。如果col1和col2上分别有一个单列索引,查询优化器会尝试去使用索引合并优化(见章节8.2.1.3,“Index Merge Optimization”),或者尝试去找到那个可以排除更多条记录的索引。如果这张表有一个多列索引,任何一个最左前缀都可以被查询优化器用来查找记录。例如,如果你有一个三列索引,包含列(col1, col2, col3),你可以快速搜索(col1),(col1,col2),和(col1, col2, col3).
如果条件列不包含索引的最左前缀列,则不能用这个索引来进行查找。假设你的select语句如下:
select * from tbl_name where col1=val1;
select * from tbl_name where col1=val1 and col2=val2;
select * from tbl_name where col2=val2;
select * from tbl_name where col2=val2 and col3=val3;
如果有一个(col1, col2, col2)组成的联合索引,只有前两个查询可以使用索引。第三个和第四个查询的确包含了索引列,但是却不能用索引来进行查询,因为(col2)和(col2,col3)不是(col1,col2,col3)的最左前缀。