简介
DB2 SQL 优化器(后文简称为优化器)可以估计每个备选访问计划的执行成本,并根据其估计结果选择一个最佳访问计划。一个访问计划可以指定用来解析一条 SQL 语句的操作次序。
为正确地确定每种访问计划的成本,DB2 优化器需要准确的基数估计值。基数估计是这样一种过程:在应用了谓词或执行了聚集之后,优化器使用统计信息确定部分查询结果的大小。对于访问计划的每个操作符,优化器将估计该操作符的基数输出。一个或更多谓词的应用可以减少输出流基数。
在计算谓词对于基数估计值的组合过滤效果时,通常会假设这些谓词彼此之间是独立的。然而,这些谓词可以在统计方面彼此关联。单独地处理它们通常会导致优化器低估基数值。而基数值的低估又会导致优化器选择一个次优的访问计划。
对于至少应用了至少两个本地等式谓词的 SQL 语句,优化器将考虑使用多列统计信息来检测统计关联,并更加准确地估计多个谓词组合的过滤效果。同样对于连接两个或更多表的 SQL 语句,以及在一对表间至少使用了两个等式连接谓词的连接,优化器也会使用多列统计信息。
一个本地等式谓词是一个应用于单个表的等式谓词,其描述如下所示:
其中 literal 可以是以下任一内容:
一个常量值;
一个参数标记或一个主变量;
一个专用寄存器(例如,CURRENT DATE)
一个等式连接谓词的描述如下所示,它用于表 1 和表 2 间的连接:
DB2 V8.2 使用下面的多列统计信息:
索引 keycard 统计信息:FIRST2KEYCARD、FIRST3KEYCARD、FIRST4KEYCARD 和 FULLKEYCARD
列组统计信息:列组基数值
这些统计信息描述了包含两个或更多列的列集中不同分组的数量。
在 DB2 V8.2 出现之前,只能使用索引 keycard 统计信息,并且要受下列条件约束:
索引必须是完全限定的。假如键中的所有列都可以被等式谓词 引用(连接谓词或本地谓词,但不是两者的混合),那么这个索引就是完全限定的。 对于连接谓词,索引也必须是惟一的。
在 DB2 V8.2 中,通过考虑到所有索引 keycard 统计信息而不要求索引完全限定,DB2 SQL 优化器进一步扩展了多列统计信息的使用。它还考虑到了用户收集的任何列组统计信息。本文讨论了优化器如何利用这些统计信息,以及用户如何识别要收集的列组统计信息。
多个本地等式谓词的统计相关性
DB2 SQL 优化器试图检测多个本地等式谓词间的统计相关性。
示例 1:假设有一个表 SHOW_LISTINGS,它包含如下列:
表 1. SHOW_LISTINGS 表的描述
列名 | 描述 |
SHOW_ID | 表外键,包含关于各演出清单的信息 |
CHANNEL_ID | 表外键,包含关于播放演出的每个频道的信息 |
STATION_ID | 表外键,包含和频道相关的每个电视台的信息 |
CITY_ID | 表外键,包含关于上演该演出的每个城市的信息 |
DAY | 演出播放的日期 |
TIME | 演出播放的当天的时间 |
<other columns> | 描述了演出清单的其他属性 |
由于演出只在某个电视台的某个频道播出,在一天的特定时间内,这些列(SHOW_ID,CHANNEL_ID,STATION_ID 和 TIME)彼此之间不是互相独立的。DAY 列独立于 TIME 列,但是它不独立于所有演出清单的 SHOW_ID。
设想一条应用了以下谓词的 SQL 语句:
P1: SHOW_ID = ? |
假如存在这样一个索引,其中的键包含谓词 P1-P4 引用的所有列,或者键中的前四列包含所引用的列,优化器将使用 FIRST4KEYCARD 索引统计信息(假如收集了索引统计信息的话),来检测谓词 P1-P4 之间的统计相关性。在应用了这四个谓词之后,优化器将计算一个更准确的基数估计值。例如,下面的任何一个索引可以用来检测这四个谓词间的统计相关性:
IX1 ON SHOW_LISTINGS(SHOW_ID, CHANNEL_ID, STATION_ID, TIME) |
优化器使用 IX1 的 FULLKEYCARD 和 FIRST4KEYCARD 统计信息来检测所有四个谓词的相关性。类似地,它也可以使用 IX2 和 IX3 的 FIRST4KEYCARD。
不能使用如下所示的索引:
IX4 ON SHOW_LISTINGS(CITY_ID, SHOW_ID, CHANNEL_ID, STATION_ID, TIME) |
由于每个 keycard 统计信息都将包含 CITY_ID 列,因此该列上未定义本地等式谓词。
假如不存在具有所需键的索引,那么可以在 SHOW_ID、CHANNEL_ID、STATION_ID 和 TIME 上收集列组统计信息。优化器使用这些列组统计信息,运用与处理索引的 FIRST4KEYCARD 统计信息相同的方式检测这四个谓词间的统计相关性。
DB2 优化器同样也会考虑具有谓词子集的索引或者列组统计信息。例如,看下面所示的索引:
IX5 ON SHOW_LISTINGS(SHOW_ID, STATION_ID, CITY_ID, CHANNEL_ID) |
该索引不能使用 FIRST2KEYCARD 来检测谓词 P1 和 P3 的统计相关性。尽管只是部分纠正了谓词 P1-P4 间的统计相关性,但已足以答应优化器选择一个优秀的查询执行计划。此外,尽管索引 IX5 中的完整键包含 CHANNEL_ID 列,仍然不能使用 FULLKEYCARD 统计信息来检测与 P2 的相关性,因为它包含的 CITY_ID 列没有在谓词中引用。 多个等式连接谓词的统计相关性 DB2 SQL 优化器同样尝试检测两个表中的多个等式连接谓词间的统计相关性。
示例 2:考虑示例 1 中描述的 SHOW_LISTINGS 表,另外,RATINGS 表包含如下列:
表 2. RATINGS 表的描述
列名 | 描述 |
SHOW_ID | 表外键,包含关于各演出清单的信息 |
CHANNEL_ID | 表外键,包含关于播放演出的每个频道的信息 |
STATION_ID | 表外键,包含和频道相关的每个电视台的信息 |
CITY_ID | 表外键,包含关于上演该演出的每个城市的信息 |
DAY | 播放演出的日期 |
TIME | 播放演出的时间 |
RATING | 在一天的某个时间,在特定城市中,某个电视台频道的演出清单的收视率 |
RATINGS 表包含描述不同城市演出清单的收视率信息,用户可能需要查询 RATINGS 表和 SHOW_LISTINGS 表的连接以检索这两个表的属性。一个查询在该连接上应用的谓词集包含以下内容:
P1: SHOW_LISTINGS.SHOW_ID = RATINGS.SHOW_ID |
P1-P3 这三个谓词可能不是互相独立的;优化器试图使用任何可用的多列统计信息来检测谓词之间的相关性。
优化器只能检测和说明每一对连接表上的多个连接谓词间的统计相关性。例如,假如一条 SQL 语句包含如下谓词:
P1: T1.A = T2.A |
优化器只尝试检测 P1 和 P2 间的统计相关性,因为它们只应用于相同的两个表的连接,T1 和 T2。P3 应用于 T1 和 T2 的连接;那是一个不同的连接。假如添加了第四个谓词,例如:
P4: T1.D = T2.D |
优化器将进一步尝试检测 P3 和 P4 间的统计相关性。
为了说明等式连接谓词间的统计相关性,优化器使用连接所涉及的两表之一的多列统计信息;这个表被视为连接的父表。因此只需要在连接的父表中收集列组统计信息。连接的另一个表被指定为子表。假如父表不能确定,那么优化器就不能使用多列统计信息来检测连接谓词间的统计相关性。
附录 B 提供了优化器如何确定两个连接表中的父表和子表的具体示例和描述。对连接中的父表进行标识,或者判定连接中是否有父表,这对于避免收集无用的列组统计信息是非常有用的。假如尚无合适的索引可用,那么在连接中的每个表上收集列组统计信息即可。