文档首页
MySQL 8.4 参考手册
相关文档 下载此手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  多列索引

10.3.6 多列索引

MySQL 可以创建组合索引(即,在多个列上创建索引)。索引最多可以包含 16 列。对于某些数据类型,您可以索引列的前缀(请参阅 第 10.3.5 节,“列索引”)。

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)
);

name 索引是在 last_namefirst_name 列上创建的索引。此索引可用于在查询中查找,这些查询在 last_namefirst_name 值的组合中指定已知范围内的值。它也可以用于只指定 last_name 值的查询,因为该列是索引的最左侧前缀(如本节后面所述)。因此,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 索引 用于以下查询中的查找

SELECT * FROM test WHERE first_name='John';

SELECT * FROM test
  WHERE last_name='Jones' OR first_name='John';

假设您发出以下 SELECT 语句

SELECT * FROM tbl_name
  WHERE col1=val1 AND col2=val2;

如果在 col1col2 上存在多列索引,则可以直接获取相应的行。如果在 col1col2 上存在单独的单列索引,则优化器尝试使用索引合并优化(请参阅 第 10.2.1.3 节,“索引合并优化”),或者尝试通过确定哪个索引排除更多行并使用该索引获取行来找到最严格的索引。

如果表具有多列索引,则优化器可以使用索引的最左侧前缀来查找行。例如,如果您在 (col1, col2, col3) 上有一个三列索引,那么您将在 (col1)(col1, col2)(col1, col2, col3) 上具有索引搜索功能。

如果列不构成索引的最左侧前缀,则 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) 的最左侧前缀。