MySQL可以创建组合索引(即 多列上的索引)。一个索引最多由16列组成,对于某些数据类型,你可以索引一个列的前缀,即前缀索引,可以只索引一个字段的指定部分内容
例如:
`CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));`
MySQL 可以使用多个列的索引,测试索引中的所有列,或者只测试第一列,前两列,前三列等等,以此类推,如果在索引的定义中按照正确的顺序指定列,单个组合索引可以加速同一个表的多种查询速度
多列索引可以视为排序数组
注意:
作为复合索引的替代方法,可以引入一个基于其他列的信息“散列”的列。如果这个列很短,合理地唯一,并且有索引,那么它可能比许多列上的“宽”索引要快。在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)
);
以下查询时组合索引是生效的:
SELECT * FROM test WHERE last_name='Jones';
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索引在以下的sql查找中并没有使用到:
SELECT * FROM test WHERE first_name='John';
SELECT * FROM test
WHERE last_name='Jones' OR first_name='John';
假设使用了以下类似的sql:
SELECT * FROM tbl_name
WHERE col1=val1 AND col2=val2;
如果col1和col2上存在多列索引,则可以直接获取相应的行。如果col1和col2上存在单独的单列索引,那么优化器将尝试使用索引合并优化,或者通过确定排除更多行的索引并使用该索引获取行来尝试查找限制性最强的索引
如果表有多列索引,则优化器可以使用索引的任何最左侧前缀来查找行。例如,如果在(col1,col2,col3)上有一个三列索引,则在(col1)、(col1,col2)和(col1,col2,col3)上有索引搜索功能。
如果sql条件中的列无法组成索引最左边的前缀的方式,MySQL就不能使用索引执行查找。
假设如下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, col3)存在索引,那只有前两个查询是用到索引的,后两个查询确实包含了索引列,但是并没有用上索引,因为(col2),(col2, col3) 并不是(col1, col2, col3)的最左前缀,也就是不符合最左原则