Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - SQL 的用法 » 查询处理 » 查询优化与执行 » 提高查询性能 » 索引 » 提高索引性能

 

复合索引

索引可以包含一个、两个或多个列。两个或更多个列上的索引被称作复合索引。例如,以下语句会创建一个具有两列的复合索引:

CREATE INDEX name
ON Employees ( Surname, GivenName );

如果第一列不能单独提供较高的选择性,复合索引将会非常有用。例如,如果许多雇员都同姓,则 Surname 和 GivenName 上的复合索引非常有用。因为每个雇员都有唯一的 ID,所以 EmployeeID 和 Surname 上的复合索引可能没有用处,因此列 Surname 不会提供任何附加选择性。

利用索引中的附加列,您可以缩小搜索的范围,但使用一个具有两列的索引不同于使用两个单独的索引。复合索引的结构与电话簿类似,它首先按姓对雇员进行排序,然后按名对所有同姓的雇员进行排序。如果您知道姓,电话簿将非常有用,如果您知道名和姓,电话簿则更为有用,但如果您只知道名而不知道姓,电话簿将没有用处。

列顺序

在创建复合索引时,应仔细考虑列的顺序。对索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引非常有用;仅对后面的任意列执行搜索时,复合索引并没有用处。

如果您要仅对一个列执行多次搜索,则该列应该是复合索引中的第一个列。如果您要对一个两列索引中的两个列都执行单独搜索,则应创建另外一个仅包含第二列的索引。

例如,假定您在两个列上创建一个复合索引。其中一列包含雇员的名,另一列包含雇员的姓。您可以创建一个先包含名后包含姓的索引。或者,您也可以创建一个先包含姓后包含名的索引。虽然这两个索引都以两个列组织信息,但它们具有不同的功能。

CREATE INDEX IX_GivenName_Surname
   ON Employees ( GivenName, Surname );
CREATE INDEX IX_Surname_GivenName
   ON Employees ( Surname, GivenName );

假定您需要搜索指定的名字 John。唯一有用的索引是在索引的第一列包含指定名字的索引。由于名为 John 的雇员会出现在索引中的任意位置,因此先按姓再按名组织的索引没有用处。

如果您更可能仅按名或仅按姓查找雇员,则应考虑创建这两个索引。

或者,您也可以创建两个索引,每个索引仅包含一个列。但是请记住,SQL Anywhere 在处理单个查询时只使用一个索引来访问任何一个表。即使您知道名和姓,SQL Anywhere 也可能需要读取额外的行,以查找包含正确姓的行。

当使用 CREATE INDEX 命令创建索引时(如上例所示),列会按命令中所示的顺序显示。

复合索引和 ORDER BY

缺省情况下,索引的列按升序排列,但您可以选择通过在 CREATE INDEX 语句中指定 DESC 来将这些列按降序排列。

只要 ORDER BY 子句仅包含索引中的列,SQL Anywhere 就可以选择使用索引来优化 ORDER BY 查询。此外,索引列的排序方式必须与 ORDER BY 子句完全相同或完全相反。对于单列索引,这种排序方式始终会使查询可以得到优化,但复合索引则需要稍微多考虑一些问题。下表显示了一个两列索引的可能性。

索引列 可优化的 ORDER BY 查询 不可优化的 ORDER BY 查询
ASC、ASC ASC、ASC 或 DESC、DESC ASC、DESC 或 DESC、ASC
ASC、DESC ASC、DESC 或 DESC、ASC ASC、ASC 或 DESC、DESC
DESC、ASC DESC、ASC 或 ASC、DESC ASC、ASC 或 DESC、DESC
DESC、DESC DESC、DESC 或 ASC、ASC ASC、DESC 或 DESC、ASC

含有两个以上的列的索引遵循上述一般规则。例如,假定您有以下索引:

CREATE INDEX idx_example
ON table1 ( col1 ASC, col2 DESC, col3 ASC );

在这种情况下,以下查询可以得到优化:

SELECT col1, col2, col3 FROM table1
ORDER BY col1 ASC, col2 DESC, col3 ASC;
SELECT col1, col2, col3 FROM example
ORDER BY col1 DESC, col2 ASC, col3 DESC;

索引不用于优化在 ORDER BY 子句中具有 ASC 和 DESC 的任何其它模式的查询。例如,以下语句不会被优化:

SELECT col1, col2, col3 FROM table1
ORDER BY col1 ASC, col2 ASC, col3 ASC;