本文讲述的是在DB2 优化器中如何使用分布统计信息?我们大家都知道DB2 优化器是一种基于成本的优化器。它是根据表与实际操作索引的相关统计信息作出决策。DB2 在生成统计信息时,不但能提供基本统计信息,还允许创建所谓的分布统计信息。
本文解释什么是分布统计信息、分布统计信息在哪些情况下尤为重要,以及应用程序开发人员应该考虑些什么,才能使 DB2 优化器创建有效的访问计划。
简介
为了执行查询或 DML 语句(INSERT、UPDATE、DELETE),DB2 必须创建一个访问计划(access plan)。访问计划定义按什么顺序访问表,使用哪些索引,以及用何种连接(join)方法来关联数据。好的访问计划对于 SQL 语句的快速执行至关重要。DB2 优化器可以创建访问计划。这是一种基于成本的优化器,这意味着它是根据表和索引的相关统计信息来作出决策的。
DB2 在生成统计信息时,不但能提供基本统计信息,还允许创建所谓的分布统计信息。不但数据库管理员要理解分布统计信息,而且应用程序开发人员也要理解分布统计信息。应用程序开发人员必须小心谨慎,因为在某些情况下分布统计信息对于 DB2 优化器来说非常重要。
主变量或参数标记(在 Java 中为 java.sql.PreparedStatement)的使用可能会造成阻碍,使优化器无法***限度地利用分布统计信息。本文解释什么是分布统计信息、分布统计信息在哪些情况下尤为重要,以及应用程序开发人员应该考虑些什么,才能使 DB2 优化器创建有效的访问计划。
基本统计信息和分布统计信息
在研究分布统计信息之前,我们先来看看基本统计信息,只要执行 RUNSTATS 即可收集这些表的相关统计信息。
表的相关统计信息:
当前使用的页面数
包含记录行的页面数
溢出的行数
表中的行数(基数)
对于 MDC 表,还有包含数据的块(block)数
表中各列的相关统计信息:
列的基数
列的平均长度
列中第二大的值
列中第二小的值
列中 NULL 值的个数
通常,执行 RUNSTATS 时,不但可以收集到关于表的统计信息,而且还可以收集到相应的索引的相关统计信息。要了解为索引而收集的统计信息,请参阅 DB2 Administration Guide: Performance - Statistical information that is collected。
观察一个表的基本统计信息,您可以看到,DB2 优化器知道一个表由多少行组成(表的基数),以及一个列包含多少个不同的值(列的基数)。但是,还有一些信息是基本统计信息无法提供的。例如,基本统计信息不能告诉优化器一个列中某些值出现的频率。假设表 TABLE_X 有大约 1,000,000 行,在该表上执行这样一条查询:
SELECT * FROM TABLE_X WHERE COLUMN_Y = 'VALUE_Z'
难道 DB2 优化器知道 TABLE_X 中有多少行满足条件 COLUMN_Y = 'VALUE_Z' 不重要吗?换句话说:知道这个查询将返回 1 行、100 行、1000 行还是 10000 行有什么不好呢?
实际上,通过基本统计信息,DB2 优化器只能估计 'VALUE_Z' 在 COLUMN_Y 中出现的频率。在这种情况下,优化器认为所有值在 COLUMN_Y 中是平均分布的,这意味着它认为所有的值都有相同的出现频率。如果事实碰巧如此,这样估计并无大碍。但是,如果有些值比其他值出现得更频繁一些(例如,如果 'VALUE_Z' 出现 900,000 次,即占所有行的 90%)。
那么DB2 优化器不能考虑到这一点,因而生成的访问计划就不是***的。而分布统计信息可以填补这一空白。分布统计信息可以提供关于数据出现频率及其分布情况的信息,如果数据库中存储了很多重复值,并且数据在表中并非平均分布的时候,分布统计信息对于基本统计信息是一个重要的补充。
分布统计信息的类型 —— 频率(frequency)统计信息和分位数(quantile)统计信息
有两种不同类型的分布统计信息 —— 频率统计信息和分位数统计信息。让我们通过一个示例表来研究一下这两种不同类型的分布统计信息。
示例表 “CARS” 表示一家汽车制造商,对于生产的每一辆汽车,在表中都有相应的一行。每辆汽车可以由它的 ID 来标识,因此 “ID” 是表 “CARS” 的主键(PK)。此外,表中有一个 “STATE” 列,表明汽车当前处在制造流程中的哪一步。一辆汽车的制造流程从第 1 步开始,然后是第 2 步、第 3 步,...、第 49 步、第 50 步、第 51 步、...、第 98 步、第 99 步。
一直到第 100 步 —— 第 100 步意味着汽车已经完工了。已完工的汽车所对应的行仍然保留在表中,后续流程(例如投诉管理、质量保证等)仍要用到这些行。汽车制造商生产 10 种不同型号(“TYPE” 列)的汽车。为了简化问题,在这个示例表中,各种汽车型号命名为 A、B、C、D、...、J。除主键索引(在 “ID” 列上)之外。
“STATE” 列上也有一个索引(“I_STATE”),在 “TYPE” 列上还有一个索引(“I_TYPE”)。实际上,一个 “CARS” 表包含的列远不止 “ID”、“STATE” 和 “TYPE”。为简单起见,示例表中没有出现其他这些列。
频率统计信息
假设表 CARS 现在有大约 1,000,000 条记录,不同的型号在表中出现的频率如下所示:
表 1. 表 CARS 中 TYPE 列的频率统计信息
- TYPE COUNT(TYPE)
- A 506135
- B 301985
- C 104105
- D 52492
- E 19584
- F 10123
- G 4876
- H 4589
- I 4403
- J 3727
型号为 A 的汽车最受购买者的青睐,因此生产的汽车中大约有 50% 是这种型号。型号 B 和型号 C 仅次于型号 A ,分别占所有汽车的 30% 和 10%。其他所有型号加在一起仅占 10%。
上面的表显示了 “TYPE” 列的频率统计信息。通过基本统计信息,DB2 优化器只能了解到该表包含 1,000,000 行(表的基数)和 10 种不同的值(型号),即 A 到 J。如果没有分布统计信息,优化器会认为每种值以相同的频率出现,大约都是出现 100,000 次。
而一旦生成了关于 “TYPE” 列的分布统计信息,优化器即可了解每种型号真正的出现频率。因此,DB2 优化器清楚各种已有型号出现的不同频率。
优化器使用频率统计信息来计算用于检查相等或不等的谓词的过滤因子。例如:
- SELECT * FROM CARS WHERE TYPE = 'H'
分位数统计信息
与频率统计信息不同,分位数统计信息与不同值的出现频率无关,而与一个表中有多少行小于或大于某个值(或者有多少行介于两个值之间)相关。分位数统计信息提供关于一个列中的值是否聚合的信息。为获得这样的信息,DB2 假定列中的值是按升序排列的,并根据正则行间隔确定相应的值。
我们来看看表 CARS 中的 “STATE” 列,该列按升序排列。根据正则行间隔,即可确定 “STATE” 的对应值。
表 2. CARS 表中 STATE 列的分位数统计信息
- COUNT(row) STATE ASC
- 5479 1
- 54948 10
- 109990 21
- 159885 31
- 215050 42
- 265251 52
- 320167 63
- 370057 73
- 424872 84
- 475087 94
- 504298 100
- ... 100
- 1012019 100
由于已完工的汽车仍然没有从表中删除,因此状态为 100 (=完工)的汽车数量比所有处于其他状态的汽车总和还多。已完工的汽车占表中所有记录的 50%。
注意: 在实际情况下,已完工的汽车数量甚至还要更多(例如超过 99%)。在后文中的具体例子中可看到这种情况。
上表显示了 “STATE” 列的分位数统计信息。有了这种关于有多少行分别小于和大于确定值的信息,优化器即可计算出用于测试小于(小于等于)、大于(大于等于)或介于两值之间的谓词的过滤因子。例如:
- SELECT * FROM CARS WHERE STATE < 100
- SELECT * FROM CARS WHERE STATE BETWEEN 50 AND 70
根据已有的分位数统计信息计算出来的过滤因子不是很精确,但即使只收集 20 个值,其误差仍然低于 5%。
完整内容的学习,请访问:
http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0606fechner/
【编辑推荐】