myfriend2010的博客
===========================================================
db2 分析函数的一篇文章
===========================================================

--OLAP:DB2® Universal Database 中引入的在线分析处理(OLAP)函数,这些函数扩展了关系模型、使关系模型能够理解行集合内的排序方式(ordering)。
排列函数 第一类引入到 DB2 中的 OLAP 函数是 排列(ranking)函数,它们是在 DB2 Version 6 中引入的。这些排列函数提供了定义一个集合(使用 PARTITION 子句),然后根据某种排序方式对这个集合内的元素进行排列的能力。例如,假设我们有一个雇员表,现在要对每个部门内的雇员薪水进行排列。要实现这一点,我们需要一个函数调用,这个函数调用可以完成以下工作:
将分区(集合)定义为各个部门,将集合内的排序方式定义为按薪水排序。 按照惯例,我们一般会将薪水高的排在前面,所以我们将指定一个对薪水的降序排序方式。下面的例子展示了这个查询的查询和输出。
select empnum, dept, salary, rank() over (partition by dept order by salary desc nulls last) as rank, dense_rank() over (partition by dept order by salary desc nulls last)as denserank, row_number() over (partition by dept order by salary desc nulls last)as rownumber from emptab;

EMPNUM DEPT SALARY RANK DENSERANK ROWNUMBER
------ ---- ------ ---- --------- ---------
6 1 78000 1 1 1
2 1 75000 2 2 2
7 1 75000 2 2 3
11 1 53000 4 3 4
5 1 52000 5 4 5
1 1 50000 6 5 6
--------------------------------------------------
9 2 51000 1 1 1
4 2 - 2 2 2
注意,rank 函数本身没有参数。这是因为 rank 函数不对任何参数执行任何计算。相反,rank 函数只是着眼于行集合--以及每一行在集合中的位置--正如排序方式所定义的那样。那么,我们如何为这个函数定义集合和排序方式呢?两者都是用 OVER 子句定义的。在这个例子中,因为我们要在每个部门内进行排列,因此我们通过按部门划分分区来定义集合。这样做的效果是可以确保只有那些在 dept 列具有相等值的行才参与排列。对排列函数的而言, 分区(partition) 和 集合(set)这两个术语是等价的。在 PARTITION 子句后面,我们有一个 ORDER BY 子句,这个子句定义了分区内的排序方式。在这里,我们想将高薪排在前面,因此我们将排序方式定义为降序。除了指定降序以外,我们还指定 NULLS LAST。在 SQL 中,空值排在前面,意即空值显得要大于所有其他非空的值。这就给排列带来了问题,因为我们可能并不想将为空的薪水排在前面。因此,我们使用 NULLS LAST 子句来更改默认的排序方式,这样就可以将空值排在后面了。(注意,NULLS LAST 子句是在 DB2 V7 中引入的;不过,在 V6 中使用一个 CASE 表达式来强加排序方式也是可以的。) 现在,让我们看一下输出。前 6 行都是 Department 1 的雇员,每一行都被赋予一个按薪水降序排列所得的名次。注意,在 Department 1 中,有两个雇员的薪水都是 75000,这两行都被赋予第二的名次。这是因为 rank 函数提供了一种 “奥林匹克式”的排列方式,在这种方式中,两个相等的值得到相等的名次。因为有两行“结在一起,同获第二”,所以就没有排在第 3 的行。相反,接下来的一行排在第 4,因为根据排序方式,有 3 行严格地排在这一行之前。 对于 Department 2,注意其中有一个行具有为空的薪水。因为我们指定了 NULLS LAST,所以这一行被排在非空行的后面。如果我们没有指定 NULLS LAST 的话,Department 2 中两行的排列顺序就要倒过来了。 到现在,您可能会问自己,在上面的例子中,其他两个输出列 denserank 和 rownumber 是什么呢?DB2 实际上有三个不同的排列函数。首先是 rank 函数,它提供了奥林匹克式的排列方式,这在前面已经描述过了。其他两个函数分别是 dense_rank和 row_number。Dense_rank 很像 rank,在这个函数中,“结”中的行排名是相等的。这两个函数惟一的不同之处在于对跟在结后面的值的处理方式,在 Dense_rank函数中排名是按 1 递增的(而不是像 rank 函数那样按结中行的数量来递增)。因而,这里不会出现排名有间隔的现象(因此函数名中才用了“dense”)。虽然 Employee 11 的薪水在 rank 函数中获得的名次是第 4,但是 denserank 函数返回的值是 3。 最后一列给出 row_number 函数的输出。Row_number 也执行一次排列,但是当碰到有结的情况时,结中的行要进行任意的(也就是说,不是确定的)排序。这在对有重复值的数据进行分析时很有用。row_number 函数一个有趣的方面是它是惟一不要求提供排序方式的排列函数。如果在没有指定排序方式的情况下调用 row_number 函数,则所有的行都将被当作结中的行来对待,因而这些行是任意排序的。这对于在输出中给行排序来说很有用。
在 DB2 Version 7 中还引入了许多其他的 OLAP 函数。在引入这些函数之前,DB2 支持两类基本的函数,分别是 标量(scalar)函数聚集(aggregate) 函数。标量函数是那些对单个行中的值进行操作、并在每一行返回一个结果的函数。arithmetic 和 string 函数就是标量函数的例子。例如,下面的查询使用了 DIGITS 标量函数来格式化 salary 字段。

该函数对每一行执行结果计算,并且该计算只使用当前行中的 salary 值。

select empnum, salary, digits(salary) as digits from emptab where dept = 1;

EMPNUM SALARY DIGITS
----------- ----------- ----------
1 50000 0000050000
2 75000 0000075000
5 52000 0000052000
聚集函数(也叫 列 或 集合 函数)的行为有所不同。聚集函数对一组行进行操作,并在输出中将这些行聚集(或者合并)到单个的行中。聚集函数的一个例子是 sum 函数,这个函数计算一组值的和,并将这个和放入一个结果行中。例如,下面的查询计算每个部门中所有雇员薪水的总和。GROUP BY 子句用于表明要聚集的集合(或分区)是各个部门中所有行的集合。对于每个部门都返回一行,给出该部门中所有薪水的总和。
select dept, sum(salary) as sum from emptab group by dept;
DEPT SUM
----------- -----------
1 383000
2 51000
3 209000
- 84000

在 DB2 V7 中引入的 OLAP 函数引入了一类新的函数,我们称之为 标量-聚集(scalar-aggregate) 函数。这些函数像标量函数,因为它们也是在每一行返回单个的值,但是它们也像聚集函数,因为它们要对一个集合中多个行中的值执行计算,以计算出结果。下面的标量-聚集函数执行的是与 sum 聚集函数一样的计算,但是这个函数返回的是没有合并行的结果:

select dept, salary, sum(salary) over (partition by dept) as deptsum, avg(salary) over (partition by dept) as avgsal, count(*) over (partition by dept) as deptcount, max(salary) over (partition by dept) as maxsal from emptab;
DEPT SALARY DEPTSUM AVGSAL DEPTCOUNT MAXSAL
----- ------- - ------- ------- --------- --------
1 50000 383000 63833 6 78000
1 75000 383000 63833 6 78000
1 52000 383000 63833 6 78000
1 78000 383000 63833 6 78000
1 75000 383000 63833 6 78000
1 53000 383000 63833 6 78000
2 - 51000 51000 2 51000
2 51000 51000 51000 2 51000
3 79000 209000 69666 3 79000
3 55000 209000 69666 3 79000
3 75000 209000 69666 3 79000
- - 84000 84000 2 84000
- 84000 84000 84000 2 84000

注意,该查询没有包含 GROUP BY 子句。相反,该查询使用了 OVER 子句来对数据分区,以便 sum 函数对同一部门中的行执行计算,并在每一个部门内的每一行中返回该部门所有薪水的总和。按惯例,为了在每一行中包括那样的聚集结果,我们需要使用一个联合,但是现在 OLAP 函数为此提供了更简易的模式。我们推荐使用这种类型的函数作为 报告 函数,因为这种函数是对集合计算总和,并在每一行中都报告一次结果的。我曾经在前面和后面的例子中使用了 SUM, 但是大部分聚集函数(例如 AVG、MIN、MAX、STDEV,等等)都使用 OVER 子句。在 DEPTSUM 列右边的其他列显示了平均薪水、部门中雇员的人数以及部门中的最高薪水。惟一不支持作为标量-聚集函数的聚集函数是线性回归函数。

这些报告函数一个强大的用处就是计算比率和百分比。要计算某个雇员的薪水占整个部门薪水总和的百分比,只需简单地用报告的薪水总和去除该雇员的薪水。

select empnum, dept, salary, sum(salary) over (partition by dept) as deptsum, decimal(salary,10,2) / sum(salary) over(partition by dept) as percentage from emptab;
EMPNUM DEPT SALARY DEPTSUM PERCENTAGE
------ ----- -------- ----------- --------

1 1 50000 383000 0.1305
2 1 75000 383000 0.1958
5 1 52000 383000 0.1357
6 1 78000 383000 0.2036
7 1 75000 383000 0.1958
……
如果我们在要进行聚集的集合中引入一个排序方式,会出现什么情况呢?答案是,我们不处理一个 报告( reporting ) 函数,而是处理一个 累加( cumulative )函数。累加函数是一种标量-聚集函数,它对当前行 以及集合中当前行之前(相对排序方式而言)的所有行进行操作。让我们为这个例子使用一个不同的表。假设我们有一个这样的表,它记有当前历年的每月销售业绩。那么,我们如何计算每个月的 年至今日(year-to-date) 销售数字呢?这里,我们要计算每月销售的累加和。我们可以这样做:

select date, sales, sum(sales) over (order by date) as cume_sum, count(*) over (order by date) as setcount from sales where year(date) = 2000;
DATE SALES CUME_SUM SETCOUNT
---------- ------------ ------------ ---------
01/01/2000 968871.12 968871.12 1
02/01/2000 80050.05 1048921.17 2
03/01/2000 757866.14 1806787.31 3
04/01/2000 58748.13 1865535.44 4
05/01/2000 40711.69 1906247.13 5
06/01/2000 241187.78 2147434.91 6
07/01/2000 954924.16 3102359.07 7
08/01/2000 502822.96 3605182.03 8
09/01/2000 97201.45 3702383.48 9
10/01/2000 853999.45 4556382.93 10
11/01/2000 358775.59 4915158.52 11
12/01/2000 437513.35 5352671.87 12

每月销售量和到当前日期的累加销售量

让我们看一下结果。对于第一行,累加和就等于这一行的销售量。对于第二行,累加和等于一月份和二月份销售量的和(968871.12 + 80050.05 = 1048921.17)。类似地,第三行的结果是一月份、二月份和三月份销售量的和。在 CUME_SUM 列右边的列执行一个累加计数,给出在集合中行的数量。例如,第一行只有一行被求和(也就是该行本身),第二行有两行被求和(该行本身以及前一行),依此类推。上面的图给出了销售数字以及在前面的查询中计算出的累加和的图形化表示。

如果我们有多年的数据,并且想计算 每一年内 到当月的累加和,那么我们也可以像下面这样使用 PARTITION BY 子句:

select date, sales, sum(sales) over (partition by year(date) order by month(date)) as cume_sum from sales where year(date) >= 2000;
DATE SALES CUME_SUM
---------- ------------ -----------
01/01/2000 968871.12 968871.12
02/01/2000 80050.05 1048921.17
03/01/2000 757866.14 1806787.31
04/01/2000 58748.13 1865535.44
05/01/2000 40711.69 1906247.13
06/01/2000 241187.78 2147434.91
07/01/2000 954924.16 3102359.07
08/01/2000 502822.96 3605182.03
09/01/2000 97201.45 3702383.48
10/01/2000 853999.45 4556382.93
11/01/2000 358775.59 4915158.52
12/01/2000 437513.35 5352671.87
01/01/2001 476851.71 476851.71
02/01/2001 593768.12 1070619.83
03/01/2001 818597.97 1889217.80
...

使用 PARTITION BY 子句计算累加和

现在,请注意 2001年1月那一行是如何重置的。这是因为日期按年划分了分区,而在 2001年内 没有在一月份之前的行,因此 cume_sum 就等于一月份的销售量。这个例子还演示了另一件有趣的事情,那就是 OVER 子句使用的参数可以是表达式,而不仅仅是列值。
在更复杂的例子中,甚至可能会将其他的聚集函数嵌入到标量-聚集函数调用中。这很有用,因为在执行分析之前先执行某种类型的聚集(例如,将销售量聚集到月的层次上)是十分常见的。这就引发了下面的问题:何时处理标量-聚集函数?答案是在处理选择清单中剩下的部分时处理这些函数。通常,一个查询的处理顺序是这样的:
From 子句
Where 子句
Group By 子句
Having 子句
选择清单
您可以看到,选择清单是在查询的所有其他部分处理完之后才被处理的。这意味着如果您有谓语(在 WHERE 或 HAVING 子句中),或者您有任何作为 GROUP BY 子句结果的聚集,那么在处理标量-聚集函数之前首先要应用这些东西。例如,让我们看下面的查询:

select year(date) as year, sum(sales) as sum, sum(sum(sales)) over (order by year(date)) as cume_sum from sales where year(date) >= 1995 group by year(date);
YEAR SUM CUME_SUM
----------- ------------- ------------
1995 7731162.39 7731162.39
1996 4127017.98 11858180.37
1997 7211584.76 19069765.13
1998 4149296.50 23219061.63
1999 6278023.54 29497085.17
2000 5352671.87 34849757.04
2001 5736777.81 40586534.85

对一个聚集的累加和

在这个例子中,我们访问表(在 FROM 子句中指定)并应用 WHERE 子句,然后应用 GROUP BY 子句并计算每年的销售总量。最后,我们处理选择清单,包括所有的标量-聚集函数。

这里还要讲一点。因为标量-聚集函数是在 WHERE 子句 之后处理的,因此在一个谓语中引用标量-聚集函数是不可能的。相反,如果您想这么做,您就必须 嵌套 标量-聚集函数调用,要么是嵌套在一个公共表表达式内,要么是嵌套在一个嵌套查询内。这在执行返回前 n 行结果的查询时变得很有用。

一个这样例子就是编写一个用于选择具有最高销售总量的3年的查询。我们可以通过对每年的销售量排列、然后选择名次为 3 或者更小的行这种方法来做这件事。

with ranked_years (year, sum, rank) as (select year(date) as year, sum(sales) as sum, rank() over (order by sum(sales) desc) as rank from sales group by year(date) ) select year, sum, rank from ranked_years where rank <= 3;
YEAR SUM RANK
----------- ------------- -------
1995 7731162.39 1
1997 7211584.76 2
1999 6278023.54 3

Top n查询的例子

在这个例子中您可以看到,我们有一个公共表表达式,它执行聚集来计算每年的销售总量,然后对销售总量进行排列。接着,外围的选择使用这个结果表并添加一个谓语,使得查询只返回那些名次 <=3(也就是销售总量排在前3名)的行。要计算中数、百分位以及其他分布统计,也可以执行类似的查询。

我希望至此我已经传达了这些新 OLAP 函数是什么以及如何使用它们的大致信息。实际上,有关这些函数的内容比我在这里描述的要多得多。因此,敬请关注另一篇更详细介绍这些函数的文章。

我想告诉你的是,DB2 已经使用这些 OLAP 函数的实现扩展了关系模型,因而现在关系模型就可以理解相对于数据集合的 排序方式。如果您曾经试过编制牵涉到排序方式的查询,您就知道这些查询可以变得多么的困难和复杂(即使是像中数这样的简单查询也是如此)。OLAP 函数为您提供了可以高效、简明地编制那样的查询的工具。随着对 DBMS 的需求的日益增长,显然必须将传统的关系模型加以扩展,以便能够处理那些越来越复杂的分析,而这些函数正是 DB2 打破局限的一个例子。


myfriend2010 发表于:2008.01.09 17:36 ::分类: ( db2 ) ::阅读:(224次) :: 评论 (1)
===========================================================
DB2中數据庫管理頁大小的限制
===========================================================
DB2中的限制之六數据庫管理頁大小的限制

在現實的DB2應用中大家可能經常會遇到一些錯誤,錯誤的原因是對DB2的
限制不太了解而引起的,在此我簡單地總結一下,歡迎大家繼續﹐以便和大家共享﹐
共同探討﹐共同近步﹗(以下主要以DB2 7.X為例)。

1. 一個表中的列的最大個數
4KB頁大小的限制=500
8KB頁大小的限制=1012
16KB頁大小的限制=1012
32KB頁大小的限制=1012
2. 一行的最大長度
4KB頁大小的限制=4005
8KB頁大小的限制=8101
16KB頁大小的限制=16293
32KB頁大小的限制=32677
3. 一個表的每個分區的最大規模(千兆字節)
4KB頁大小的限制=64
8KB頁大小的限制=128
16KB頁大小的限制=256
32KB頁大小的限制=512
4. 一個索引的每個分區的最大規模(千兆字節)
4KB頁大小的限制=64
8KB頁大小的限制=128
16KB頁大小的限制=256
32KB頁大小的限制=512
5. 一個選擇列表元素的最大個數
4KB頁大小的限制=500
8KB頁大小的限制=1012
16KB頁大小的限制=1012
32KB頁大小的限制=1012
6. 一個GROUP BY子語句列的最大個數
4KB頁大小的限制=500
8KB頁大小的限制=1012
16KB頁大小的限制=1012
32KB頁大小的限制=1012
7. 一個GROUP BY子語句列的最大長度(字節數)
4KB頁大小的限制=4005
8KB頁大小的限制=8101
16KB頁大小的限制=16293
32KB頁大小的限制=32677
8. 一個ORDER BY子語句列的最大個數
4KB頁大小的限制=500
8KB頁大小的限制=1012
16KB頁大小的限制=1012
32KB頁大小的限制=1012
9. 一個ORDER BY子語句列的最大長度(字節數)
4KB頁大小的限制=4005
8KB頁大小的限制=8101
16KB頁大小的限制=16293
32KB頁大小的限制=32677
10. 一個INSERT語句中數值的最大個數
4KB頁大小的限制=500
8KB頁大小的限制=1012
16KB頁大小的限制=1012
32KB頁大小的限制=1012
11. 一個UPDATE語句中數值的最大個數
4KB頁大小的限制=500
8KB頁大小的限制=1012
16KB頁大小的限制=1012
32KB頁大小的限制=1012
12. 一個常規DMS表空間的最大規模(千兆字節數)
4KB頁大小的限制=64
8KB頁大小的限制=128
16KB頁大小的限制=256
32KB頁大小的限制=512


myfriend2010 发表于:2008.01.07 18:08 ::分类: ( db2 ) ::阅读:(212次) :: 评论 (13)
===========================================================
DB2 分区特性
===========================================================

简介

在数据仓库中,事实表或历史表的大小是摆在设计人员和管理员面前的一个挑战。这些表通常包含数亿行数据,有时候甚至包含数千亿行数据。对于这种规模的表,主要关心以下几点:

  • 查询性能
  • 将大量新数据插入到这些表中
  • 每月或每个季度删除大量过时的数据

随着时间的推移,DB2 继续添加和增强特性,以解决这些需求。DB2 9 for Linux, UNIX, and Windows 中一个重要的增强是表分区特性。这导致以下问题:

  • 有哪些这样的特性?
  • 每个特性对解决上面关心的问题有什么作用?
  • 我应该使用哪些特性?
  • 如何将这些特性结合起来使用以增强效果?

这些就是本文要解决的问题。阅读本文之后,读者将可以:

  • 理解每个特性对于解决相关问题的独特作用。
  • 明白如何有效地将这些特性结合起来使用。

有了这些背景,读者就足以进一步研究他们感兴趣的特性的细节。

特性概述

三个互补的 CREATE TABLE 选项

CREATE table 语句现在提供了三种方式来组织数据库表中的数据。


表 1. DB2 特性
CREATE TABLE 语句中的子句DB2 特性名称
DISTRIBUTE BY HASHDPF —— 数据库分区特性
ORGANIZE BY DIMENSIONMDC —— 多维聚类
PARTITION BY RANGETP —— 表分区

您可以任意组合使用这些子句,以达到期望的效果。表 2 总结了与这些特性相关的术语,本文中用到的其他一些特性也列在下面。


表 2. DB2 特性术语
DB2 特性名称一部分的名称用于分区数据的列其他术语
数据分区特性(Data Partitioning Feature,DPF)数据库分区分布键(distribution key)在之前的版本中,分布键被称做分区键
多维聚类(Multidimensional Clustering,MDC)单元格,由一些块组成块索引
表分区(TP)数据分区表分区键

简要对比

每种特性都为分组表中的数据提供了独特的方法,并对解决与事实表或历史表相关的需求有独特的作用。

DPF 是最老的特性,通过它可以将数据库分成多个数据库分区。每个数据库分区有它自己的一组计算资源,包括 CPU 和存储。在 DPF 环境中,根据 CREATE TABLE 语句中指定的分区键,表中的每个行被分布到一个分区上。当处理一个查询时,请求也相应地被划分成多个部分,以便让各个数据库分区各自处理其负责的那些行。实际上,DPF 是一种可伸缩特性。DPF 可以通过增加数据库分区来提高处理能力,因此,随着表的增长,仍然可以保持较高的查询性能。这种能力常常被称作使用 DB2 的无共享架构提供线性的可伸缩性。

DPF 的作用不仅仅体现在表设计上。它还是调整和配置整个数据库系统的一种方法。现在已经有了关于配置那样的系统,以取得最佳性能、可靠性和增长的能力的建议实践。客户可以购买建议的硬件和软件以及配置,它们都放在一个称做 BCU (Balanced Configuration Unit) 的解决方案中。

MDC 是在 DB2 Version 8 中引入的,通过它可以在物理上将在多个维上具有类似值的行聚合在一起放在磁盘上。这种聚合能为常见分析性查询提供高效的 I/O。例如,对于 Product=car,Region=East,并且 SaleMonthYear = Jan09 的所有行,可以将它们存储在相同的存储位置,即所谓的块(block)。在 CREATE table 语句中定义维的时候,就为每种值的组合预留了存储空间。实际上,MDC 是一个能最大化查询性能的特性,对于数据仓库中常用的查询更是如此。这包括需要根据几个列中的值的组合选择行的查询。例如,DATE is between "Jan-01-2004" and "Feb-01-2005" AND Country IS NOT "United States" AND Product="Cell Phones"。

TP 是在 DB2 9 中引入的,与 MDC 类似,它也可以将具有近似值的行存储在一起。但是,TP 的以下特征是 MDC 所不具备的:

  • TP 支持按照一个维将一个表分区成多个数据分区。一种常见的设计是为每个月的数据创建一个数据分区。MDC 则支持定义多个维。
  • 通过 TP,用户可以手动地定义每个数据分区,包括将被包括到那个分区的值的范围。MDC 则为每种惟一的 MDC 维值组合自动定义一个单元格(并创建块来存储那个单元格的数据)。
  • 每个 TP 分区是一个单独的数据库对象(不同于其他作为单个数据库对象的表)。因此,TP 支持为 TP 表附加和卸除数据分区。卸除的分区成为一个常规表。而且,必要时可以将每个数据分区放在它自己的表空间中。

实际上,TP 不同于其他特性的优势在于为表添加或删除大量数据这个方面,即转入和转出。对于熟悉使用 Union All View (UAV) 来按日期对历史表分区的读者,TP 可以作为一种功能相似但是更为高级的解决方案。

表 3 总结了这些特性之间的比较:


表 3. DB2 特性简要对比
特性特性如何组织数据优点
DPF将行均匀地分布在多个数据库分区上可伸缩性 —— 随着数据库的增长增加计算资源(也就是数据库分区)
MDC将在多个维上具有近似值的行放在表中相同的物理位置,即所谓的块查询性能 —— 组织数据的方式有利于获得更快的检索速度,对于由多个谓词指定范围的查询尤其有效
TP将所有行放在同一个数据分区的一个指定范围的维中数据移动 —— 通过添加和删除整个数据分区,可以增加和删除大量数据

互补特性

本节详细阐述前面提出的观点,这 “三个朋友” 既是独立的,又是互补的。

当设计一个表时,对每个特性的使用可以认为是独立的。例如,

  • 是否使用 MDC 和 TP 对于决定 DPF 的分布键没有影响。
  • 一个列是否被用作 MDC 维对于是否应该将它作为表分区键没有影响,反之亦然。每个决定都可以单独做出。

每个特性的工作方式,例如索引方面,不会随着新的分区特性的引入而改变。例如,当引入 MDC 时,它的索引方面不会改变 DPF 在索引方面的工作方式。同样,当引入 TP 时,也不会改变 DPF 或 MDC 在索引方面的行为。在学习这些特性的时候,记住这一点有助于避免陷入困惑。

例如,假设您在学习 TP 的过程中碰到了 "TP has global indexes" 这个语句。那么,您应该不会推断 DPF 在处理索引方面的行为会有所变化。在这样的语句中,术语 "global" 仅仅是指索引对于多个 TP 数据分区来说是全局的。

通常来讲,一个特性不能用于解决数据库设计中与另外一个特性相关的不足或问题。值得注意的例子有:

  • TP 不能解决与 DPF 相关的问题,不管这个问题是 DPF 数据倾斜还是 DPF 中的管理活动速度降慢。不管有没有同时使用 TP,DPF 之前的补救方法仍然适用。
  • TP 不能用于纠正不好的 MDC 设计。

总之,如果存在与 DPF、MDC 或 TP 相关的问题,那么还是应该尝试适用于那个特性的解决方法。

表设计

数据仓库中的事实表(或历史表)非常适合使用上述每种特性,如下面的表 4 所示。


表 4. 事实表拥有适合使用 DB2 分区特性的特征
特性适合的表特征事实表的特征
DPF大型表 —— 大到无法仅依靠单独一组 CPU 和 I/O 通道来处理事实表是最大的数据库表。它们常常包含数亿行数据,有时候甚至包含数千亿行数据
MDC结果集返回在多个维上具有近似值的行的查询事实表(以及通常所说的数据仓库)是为支持这种类型的查询而设计的
TP这种类型的表:周期性地添加大量数据,然后在数据到期后又删除大量数据在事实表中,常常是每天都添加新数据。通常每月或每个季度删除过时的数据

表设计的经验法则

本节让您对于设计决定的性质有一个感性的认识(也仅仅是感性的认识),并给出一些经验法则。后面列出的参考资料提供了更全面的设计指南。

对于 DPF,在选择一个分布键时,应首选那种能使数据行均匀地分布在多个数据库分区上的列。当不具备这样的条件时,就会造成数据倾斜。这意味着一个或一些数据库分区承担了更重比例的表行,从而造成了性能瓶颈。具有很多不同值的列是较好的选择。还有一种考虑是选择能最大化联结性能的列。

另一个 DPF 设计决定是数据库分区的数量。数据库分区的数量不算是表设计方面的考虑。实际上,它是整个系统设计上的考虑,需要根据整个数据库预期的原始数据大小和服务器硬件的能力来决定。很多系统需要的数据库分区不超过 20 个。但是,最大的系统可能需要更多的数据库分区。由于数据仓库有越来越大的趋势,数据库分区的数量有望增加。

对于 MDC,一个关键的决定是用哪些列作为 MDC 维。设计上的挑战是找到最佳的一组维和最佳的粒度,使得组织最大化,存储需求最小化。较好的选择是具有以下一部分或全部特征的列:

  • 用于范围、等于或 IN 列表谓词
  • 用于转入、转出或其他大规模的行删除
  • 被 GROUP BY 或 ORDER by 子句引用
  • 外键列
  • 星型数据库的事实表中 join 子句中的列
  • 粗粒度,也就是说不同的值很少的列

典型的设计是用一个表示日期的列作为一个 MDC 维,再加上 0 到 3 个其他列作为其他维,例如 region 和 product_type。

对于 TP,设计决定包括选择用作表分区键的列和分区的数量。通常表分区键是基于时间的列。每个分区与每次转入的数据量相符。例如,每月转出数据的表,对于每个月的数据都有一个分区。对于 TP,在设计时需要特别考虑的一点是,需要处理不在 CREATE table 语句中定义的值范围内的行。

对于需要每月根据 sale_date 转出数据的数据库,一种典型的设计是使用 sale_date 作为表分区键,并为每个月创建一个单独的分区。

通常,有一个 MDC 维是基于时间的列,这样一来,同一个列既可以用于 MDC,又可以用于 TP。MDC 的粒度可以比 TP 数据库分区更细一些。

下面的表总结了以上几点。


表 5. 设计方面的经验法则总结
分区特性设计决定经验法则
DPF —— 用作分布键的列首选是具有很多不同值的列
MDC —— 用作 MDC 维的列一种典型的设计是选择一个表示日期的列,再加上 0 到 3 个其他列,例如 region 和 product_type
TP —— 用作表分区键的列和分区的数量选择一个基于时间的列。定义与每次转出的数据量相符的分区

设计的例子

表 6 展示了一些典型的表设计的例子。Transactions 历史表代表关系数据仓库中的一个典型的表。Recent transactions 表代表运营数据存储中的一个表,这种数据存储实际上是只有最近数据的一个数据仓库。


表 6. 表设计的例子
分区属性Transactions 历史表Recent transactions 表
DPF —— 用作分布键的列Transaction IDTransaction ID
DPF —— 数据库分区的数量204
MDC —— 用作维的列Transaction date(Year+Month)=36 values (见注 1);Account type=5 values; State=51 valuesTransaction date(days)=90 values; Account type=5 values; State=51 values
TP —— 用作表分区键的列和分区的数量Transaction date(Year+Month)=1 partition per monthTransaction date(Year+Month)=1 partition per month
其他表属性- -- -
# of rows (1 million per day)1 billion90 million
# of columns3030
# of indexes415

注 1:对于 Transactions 历史表上的 MDC 维,另一种设计方案是以更细的粒度定义 Transaction 日期,例如每周或每天。更好的查询性能与增加的存储需求之间的平衡取决于数据和查询的特征。

再添上 MQT

MQT 简介

阐明了以上三个特性相互区别、相互补充的关系之后,有必要进一步扩大讨论,谈一谈 MQT(物化查询表)。MQT 和分区特性都是为在相同的情况下(即数据仓库事实表或历史表)使用而设计的。因此,为了全面考虑如何使用本文中谈到的分区特性,需要解决涉及到 MQT 的情况下的一些特殊的考虑。

MQT 是基于一个查询的结果而定义的表。从另一种角度来看,MQT 就像结果集存储在一个表中的一个视图。MQT 可以提高涉及以下方面的复杂查询的响应时间:

  • 基本表中的数据上的聚类或计算
  • 基本表的联结
  • 一个或多个较大基本表中常被访问的一部分数据。

当基本表中的数据发生改变时,需要相应地更新 MQT。MQT 特性为适应各种运营需求而进行更新提供了多种选项。

与分区特性比较

下面的表为表 3 增加了关于 MQT 的一行。


表 7. DB2 特性简要对比,包括 MQT
特性特性如何组织数据优点
DPF将行均匀地分布在多个数据库分区上可伸缩性 —— 随着数据库的增长增加计算资源(也就是数据库分区)
MDC将在多个维上具有近似值的行放在表中相同的物理位置,即所谓的块查询性能 —— 组织数据的方式有利于获得更快的检索速度,对于由多个谓词指定范围的查询尤其有效
TP将所有行放在同一个数据分区的一个指定范围的维中数据移动 —— 通过添加和删除整个数据分区,可以增加和删除大量数据
MQT将查询的结果存储在一个表中查询性能 —— 对于涉及较高代价的操作,例如复杂的联结和表扫描的查询,预先计算其结果集并存储(物化)结果集

与分区特性一起设计 MQT

与分区特性一起设计 MQT 时,在设计上的考虑可以总结为以下几点:

  • 可以在使用分区特性的任意组合的表上创建 MQT。例如,可以在一个或多个使用 MDC 和 TP 的表上创建 MQT。基本表上分区特性的使用不需要考虑将来是否会在这个表上创建 MQT。然而,MQT 的设计却可能受到基本表上使用的分区特性的影响。例如,如果基本表使用了 DPF 进行分区,那么 MQT 的设计就应该考虑是否要在各个数据库分区上复制 MQT。
  • MQT 也可以使用分区特性。例如,可以使用 MDC 或 TP 对 MQT 分区。

典型的设计

接下来进一步介绍前面的 Transactions 历史表的例子,下面是这些表上定义的一些 MQT:

  • MQT 1 - transaction totals per day per account type
  • MQT 2 - Year-to-Date totals per state

关键考虑:查询性能

对这一考虑的描述

现在我们来看看在评价和使用这些特性时关键的考虑角度:性能,尤其是通常的数据仓库业务的用户查询的性能。这些查询有以下特征:

  • 从事实表中选择在几个维上符合标准的行。这意味着要将几个维表与事实表相联结。
  • 使用分组或聚类函数,例如 COUNT、GROUP BY 和 ORDER BY。
  • 返回包括很多行的结果集,从数千行到数百万行。
  • 这些查询是由用户或他们的 BI 工具生成的。这意味着这些查询更多情况下是临时性的,事务处理系统中的性能测试和调优方法对于它们并不适合。

虽然人们倾向于想到更快的性能,但最好还是说成更好的 性能。谈到性能,就应该包括以下一些方面:

  • 峰值查询执行性能
  • 查询执行性能的稳定性
  • 对于数据仓库中各种具有不同特征的工作负载的性能
  • 设计数据库以达到性能目标是否容易
  • 为达到性能目标需要付出的代价

与过去相比,现在在设计数据库以达到性能目标的过程中还需要考虑的一点是硬件的发展趋势。随着 CPU 处理能力的不断提高以及存储设备容量的不断扩大,I/O 带宽是一个潜在的性能瓶颈。在这种环境下,I/O 效率是设计时要关键考虑的一点。

本节阐释每个分区特性对查询执行性能的作用。在后面的小节中我们还会谈到转入和转出的性能。

DB2 分区特性发挥作用

使用 DPF 与不使用 DPF 相比可以提供更多的计算资源,从而对性能产生积极的影响。当 DB2 优化器为一个查询形成查询访问计划时,它将工作划分到多个数据库分区上,这些数据库分区是并行工作的。之后,再收集各个数据库分区上得到的结果,并返回给查询提交者。

MDC 对性能的贡献在于提高检索数据的效率。在多个维上具有近似值的数据存储在相同的位置,这使得 I/O 操作变得更高效,而 I/O 操作正是数据仓库中一个常见的瓶颈。而且,MDC 特性还包括块索引,在块索引中,对于每个块的数据(而不是每一行的数据)都有一个条目。这使得执行索引操作时有更高的效率。为了发挥它潜在的性能,必须为 MDC 表设计一组最佳的(或者至少是够好的)维。MDC 只对那些包括维列的查询有好处。MDC 对于查询是完全透明的。最后,MDC 在管理方面有两个值得注意的优点:

  • MDC 块索引意味着需要的 RID 索引更少。管理方面的一个优点是用于索引的存储空间减少了。
  • 由于新行是插在表中具有近似值的行附近的位置,因此数据仍然是聚合的,而不需要运行 REORG 实用程序。

TP 通过分区排除提高查询性能。例如,假设 Transactions 历史表有 36 个分区,每个月对应一个分区。对于一个选择过去 12 个月的数据的查询,优化器知道不必扫描这 12 个月之外的其他分区的数据。这种分区排除既适用于索引扫描,也适用于表扫描。TP 只对那些包括表分区键列的查询有利。

关键考虑:插入新数据

对这一考虑的描述

将来自运营系统的新数据插入到仓库中的事实表,这个过程称作 ETL、摄取(ingest)、填充数据仓库或者转入。下面的例子演示了可能遇到的各种情况。

例 1 - 使用 LOAD 每日摄入数据

  • 在业务日结束后,运营系统中包含五十万到两亿条记录的多个平面文件如期到来。
  • 一个客户脚本使用 DB2 Load 实用程序将每个文件装载到事实表中。这是在一个每夜批处理窗口中当表离线的时候完成的。
  • 在下一个业务日一开始,查询这个表的用户就可以看到前一天的数据。

例 2 - 使用 insert 的准实时摄取

  • 每过 30 分钟,一个包含 1 万到 10 万条记录的文件到来。
  • 当该文件到来时,用户编写的一个程序将这些记录添加到一个 staging 表中,然后使用 insert 语句将这些记录添加到事实表中。

例 3 - MQT 刷新

在有 MQT 的时候,它们被看作将新数据添加到数据仓库这个过程中的一部分。比较特别的是,这种情况下可以使用 MQT 刷新策略。通常,ETL 过程是手动地指定何时更新 MQT,而不是让更新自动发生。

  • 对于例 1,很可能是在每夜更新的所有任务完成之后立即更新。
  • 对于例 2,MQT 通常是每天更新一次。因此,即使底层的数据是周期性地更新的,访问 MQT 的查询全天返回的都是相同的结果。

DB2 分区特性发挥作用

DB2 分区特性对于转入会有帮助,但是有时候也会带来新情况,客户在转入过程中要适当考虑这一点。

通过 DPF 可以更快速地添加数据,因为每个数据库分区可以并行工作。另一方面,DPF 又需要考虑将行发送到适当的数据分区。

与不使用 MDC 相比,使用 MDC 可以改善转入过程。其优点包括:

  • 更少的物理 I/O:MDC 表的 RID 索引更少,因此在转入期间更新索引时需要的物理 I/O 更少。
  • 更快的插入:MDC 表减少了页面争用和锁,因此有助于使用多个并行的流来执行插入。
  • 并发的业务查询能拥有更好的性能:MDC 表减少了页面争用的锁,这一点同时也有利于并发业务查询的性能。

另一方面,如果使用 MDC,建议预先根据 MDC 维对数据进行排序。

在某些情况下,TP 有助于转入操作。TP 允许将行添加到一个分区,然后再在准备好的时候将那个分区附加到表上。然而,在这里的例子中,这个选项并不适用。还记得吗,我们的示例表(Transactions 历史表)对于每个月都有一个单独的分区,而我们是每天添加一次或多次数据。在这种情况下,在一个月开始之前,即这个月还没有开始每天添加数据之前,需要为这个表添加一个空白的分区。

最后,MQT 还增加了转入过程中要考虑的因素。特别是,需要决定何时更新 MQT。

关键考虑:删除数据

对这一考虑的描述

当数据在数据仓库中存放了一段时间后,对于业务用户来说它就不再有用了,因此需要删除它们,为新数据腾出空间。这个过程称作转出、清洗(purging)和归档。下面的例子演示了可能遇到的各种不同的情况。

通常,转出涉及到以下业务规则,并关系到如何使用 DB2 分区特性的问题:

  1. 删除到了一定年龄的行:这是最简单也是最常见的业务需求。在传统的历史表中,一般的期限为 36 个月。对于最近历史表,一般期限为 60 到 180 天。
  2. 根据业务规则删除到了一定年龄的行:在这种情况下,有些行虽然到了一般的退休年龄,但是仍然需要保留。例如,为了为争议或调查提供证据,可能需要保留某个历史事务。
  3. 使数据仍然可以被访问,但是释放存储:这种情况有时候称作归档,而不是转出。在这种情况下,行必须对用户查询可见,但是需要将这些很少被访问的行转移到更便宜的、性能更低的存储上。这种业务需求可以通过 Tivoli Hierarchical Storage Manager (HSM) 之类的工具来解决。

通常,MQT 也需要放进来考虑。通常,MQT 也需要更新,以删除相应的总结数据。例如,如果从事实表中删除了 2003 年 3 月的数据,那么也需要删除 MQT 中关于那个月的总结数据。

DB2 分区特性发挥作用

为了支持转出,针对不同的业务需求,DB2 分区特性有一些值得注意的特性。

先说 DPF,这个特性对转出作用不大。使用 DPF 与不使用 DPF 相比,转出操作相差不大。

MDC 和 TP 都为转出操作带来好处。在任何 DB2 版本中,一个特性可能比另一个特性提供更好的转出性能,但是随着时间的推移,这两个特性应该大致相当。在比较这些特性时,更重要的是看每个特性在某些转出情况下特有的优势。

对于基本的、常见的转出情况(也就是说,只是删除到了一定年龄的行),TP 显然是首选。如果使用 TP,那么转出可以通过一个简单的 DETACH 操作来完成。而且,TP 是惟一适合以下情况的特性:

  • 将转出的数据移动到另外一个位置(也就是说移动到一个表或数据库中),而不仅仅是删除它。
  • 使用 Tivoli HSM 之类的工具将这些较老的、很少被访问的行转移到更便宜的存储中,但是用户查询仍然可以看到它们。

MDC 是惟一适合以下情况的特性,与基本转出相比,下面这些情况要求更高,但是不大常见:

  • 客户希望在并发查询活动期间执行转出,但是他们不能接受在 DETACH 操作期间 TP 暂时需要的 zlock 的影响。
  • 客户不希望修改他们的应用程序或脚本。也就是说,他们不想用 TP 的 DETACH 语句代替他们的 DELETE 语句。
  • 客户想删除除时间维(表是在这一列上进行数据分区的)以外的其他维上的大量数据。
  • 客户想根据业务规则删除到了一定年龄的行。在这种情况下,他们可以发出一条 SELECT 语句来识别符合条件的行,然后再 DELETE 那些行。

对于 MQT,当从 MQT 中删除相应的总结数据时,建议在 MQT 上使用表分区,并与基本表定义一样的数据分区。

删除数据的其他选项

虽然转出是删除过时数据的常见方式,但是应该注意到,客户有时候也使用其他方式来删除数据,这些方式不需要借助分区特性。这些方式有:

  • 刷新表:在某些数据仓库中,整个表每年删除一次,然后装载一个替代的表,这个新表包含了除不再需要的数据以外的所有数据。
  • 清洗:在某些最近历史表中,每过一些天就删除整个表,并重新创建表,数据将放在有更长历史的另一个表中。然后,重新创建的空表又可以摄取新的数据,直到清洗日的到来。

结束语

本文介绍了以下 DB2 表设计特性:表分区、MDC、DPF 和 MQT。这些特性并肩作战,一起解决客户在查询性能、插入新数据和删除老数据方面关心的问题。下面的表总结了这些 DB2 特性如何解决各种客户需求。


表 8. DB2 特性如何解决客户需求
客户需求优点
查询性能每个特性都以它自己的方式为提高查询性能作出贡献。使用更多的特性将导致更好的性能。
转入在大多数客户场景中,MDC 可以带来最大的好处。TP 可以在某些不常见的情况下带来好处。
转出对于简单、常见的转出场景,TP 可以带来最大的好处。MDC 则适合处理 TP 不适合的其他转出情况。


myfriend2010 发表于:2008.01.07 14:55 ::分类: ( db2 ) ::阅读:(144次) :: 评论 (0)
===========================================================
db2 分区数据库概念:分区兼容性,并置
===========================================================

最近在看一些DB2的DPF方面的东西,有两个概念有一些搞不懂。
就是“分区兼容性”和“并置”两个概念。
资料是这样写的:

分区兼容性

可对分区键的对应列的基本数据类型进行比较,并可将它们声明为是分区兼容的(partition compatible)。分区兼容的数据类型具有如下属性:具有相同值但有不同类型的两个变量会按相同的分区算法映射至同一个分区号。 分区兼容性具有下列特征:

基本数据类型与另一个相同的基本数据类型兼容。
内部格式用于 DATE、TIME 和 TIMESTAMP 数据类型。它们彼此都不兼容,且都不与 CHAR 兼容。
分区兼容性不受带有 NOT NULL 或 FOR BIT DATA 定义的列的影响。
对兼容数据类型的 NULL 值的处理是完全相同的;对不兼容数据类型的 NULL 值的处理可能不相同。
用户定义的类型的基本数据类型用于分析分区兼容性。
对分区键中相同值的小数的处理是完全相同的,即使它们的标度和精度不同。
字符串中(CHAR、VARCHAR GRAPHIC 或 VARGRAPHIC)的尾部空格会被散列算法忽略。
BIGINT、SMALLINT 和 INTEGER 是兼容的数据类型。
REAL 和 FLOAT 是兼容的数据类型。
不同长度的 CHAR 和 VARCHAR 是兼容的数据类型。
GRAPHIC 和 VARGRAPHIC 是兼容的数据类型。
分区兼容性不适用于 LONG VARCHAR、LONG VARGRAPHIC、CLOB、DBCLOB 和 BLOB 数据类型,因为它们不能作为分区键。

并置
并置(collocation)是安置同一个数据库分区中包含相关数据的不同表中的行。并置的表使 DB2 可以更有效地使用连接策略。

您可能会发现,作为对特定查询的响应,两个或多个表频繁地提供数据。在此情况下,您会希望这样的表中的相关数据的位置尽可能地靠近。在数据库被物理地划分为两个或多个数据库分区的环境中,必须有一种方法可将划分的表的相关碎片尽可能地靠近。完成此过程的功能称为表并置。

当存取用于连接或子查询的多个表时,DB2(R) 通用数据库(DB2 UDB)能够识别要连接的数据是否位于相同数据库分区上。于是 DB2 就可以在存储数据的数据库分区上执行连接或子查询,而不必在数据库分区之间移动数据。这种局部地执行连接或子查询的能力具有显著的性能优点。

要发生并置,表必须:

在相同数据库分区组中,且这个数据库分区组不能处在再分配期间。(在再分配期间,数据库分区组中的表可能使用不同的分区映射 —— 它们不是并置的。)
有包含相同数量的列的分区键。
分区键的相应列是分区兼容的。
如果一个表在一个单分区数据库分区组中,且该分区组是在另一个表所在的同一个分区上定义的,那么也可以发生并置。

pub中这么回答:

比如int, char, varchar之类能够被散列的数据类型就是分区兼容性得,其他类似LOB, LF等类型不能被散列的就不是
对于并置,比如我有两个表A,B,其中A包含列c1 int, c2 char,B包含c1 varchar, c2 int
然后表A按照c1分区,表B按照c2分区,也就是说,当用户插入一行数据到表A,首先会对A.c1进行散列,然后模分区数量,把新的数据插入相应的分区,而对于表B则是对B.c2进行相同算法散列。
这样当查询select * from c1,c2 where A.c1=B.c2的时候,由于A.c1和B.c2的数据类型相同,使用相同的散列算法,如果A.c1与B.c2相等,那么他们肯定在同一分区,这样的话进行join的时候就不需要再分区间移动数据,只需要在本分区join完后向coord partition返回数据


myfriend2010 发表于:2008.01.05 09:09 ::分类: ( db2 ) ::阅读:(837次) :: 评论 (18)
===========================================================
profile使用入门 :)--pub精华!
===========================================================
profile使用入门 :)

很多开发和数据库管理人员都在为优化器问题烦恼不已。尽管很多时候优化器问题都是可以通过常规手段解决的,但是在某些特殊情况下,或者紧急情况(没有时间完整地分析问题)下,用户可以使用profile暂时强制优化器使用某些特定的操作。。。
下面是一个step by step的例子,简单地说明了怎样强制优化器使用table scan
DB21085I Instance "DB2" uses "32" bits and DB2 code release "SQL09010" with
level identifier "02010107".
Informational tokens are "DB2 v9.1.0.356", "s060629", "NT32", and Fix Pack "0".
Product is installed at "D:PROGRA~1IBMSQLLIB" with DB2 Copy Name
"DB2COPY1".

<---------------创建一个数据库
D:TEMPdb2service.perf1>db2 create db sampel2DB20000I The CREATE DATABASE command completed successfully.

D:TEMPdb2service.perf1>db2 connect to sampel2

Database Connection Information

Database server = DB2/NT 9.1.0
SQL authorization ID = TAOEWANG
Local database alias = SAMPEL2

<----------创建优化器系统表
D:TEMPdb2service.perf1>db2 "create table systools.opt_profile (schema VARCHAR(128) not null, name varchar(128) not null, profile blob (2M) not null, primary key (schema, name))"
DB20000I The SQL command completed successfully.

D:TEMPdb2service.perf1>cd ..

<----------创建用户表
D:TEMP>db2 "create table mytable (name varchar(128), id integer, salary float,phone varchar(20))"
DB20000I The SQL command completed successfully.

<-----------插入一些数据
D:TEMP>db2 "insert into mytable values ('tao wang', 12345, 100, '123-456')"
DB20000I The SQL command completed successfully.

D:TEMP>db2 "insert into mytable values ('diablo2', 12346, 101, '123-457')"
DB20000I The SQL command completed successfully.

D:TEMP>db2 "insert into mytable values ('whiterain', 123, 102, '123-458')"
DB20000I The SQL command completed successfully.

D:TEMP>db2 "insert into mytable values ('ganquan', 1255, 104, '123-459')"
DB20000I The SQL command completed successfully.

<---------别忘了runstats
D:TEMP>db2 "runstats on table taoewang.mytable"
DB20000I The RUNSTATS command completed successfully.

D:TEMP>db2 "runstats on table taoewang.mytable for indexes all"
DB20000I The RUNSTATS command completed successfully.


<-----------试试看
D:TEMP>db2 "SELECT * FROM TAOEWANG.MYTABLE WHERE ID < 1000"

NAME
ID SALARY
PHONE
-------------------------------------------------------------------------------------------------------------------------------- ----------- ------------------------ --------------------
whiterain
123 +1.02000000000000E+002 123-458

1 record(s) selected.

<--------创建explain表
D:TEMP>cd D:Program FilesIBMSQLLIBMISC

D:Program FilesIBMSQLLIBMISC>db2 -tvf EXPLAIN.DDL
.....

D:Program FilesIBMSQLLIBMISC>cd D:temp

<----------看一看现在的访问计划
D:TEMP>db2 set current explain mode explain
DB20000I The SQL command completed successfully.

D:TEMP>db2 "SELECT * FROM TAOEWANG.MYTABLE WHERE ID < 1000"
SQL0217W The statement was not executed as only Explain information requests
are being processed. SQLSTATE=01604

D:TEMP>db2 set current explain mode no
DB20000I The SQL command completed successfully.

D:TEMP>db2exfmt -d sampel2 -g TIC -w -1 -n % -s % -# 0 -o output.txt
DB2 Universal Database Version 9.1, 5622-044 (c) Copyright IBM Corp. 1991, 2006
Licensed Material - Program Property of IBM
IBM DATABASE 2 Explain Table Format Tool

Connecting to the Database.
Connect to Database Successful.
Binding package - Bind was Successful
Output is in output.txt.
Executing Connect Reset -- Connect Reset was Successful.

D:TEMP>uedit32 output.txt

<-------------现在优化器用了index scan
Original Statement:
------------------
SELECT *
FROM TAOEWANG.MYTABLE
WHERE ID < 1000


Optimized Statement:
-------------------
SELECT Q1.NAME AS "NAME", Q1.ID AS "ID", Q1.SALARY AS "SALARY", Q1.PHONE AS
"PHONE"
FROM TAOEWANG.MYTABLE AS Q1
WHERE (Q1.ID < 1000)

Access Plan:
-----------
Total Cost: 7.56853
Query Degree: 1

Rows
RETURN
( 1)
Cost
I/O
|
1
FETCH
( 2)
7.56853
1
/----+---
1 4
IXSCAN TABLE: TAOEWANG
( 3) MYTABLE
0.00630865
0
|
4
INDEX: TAOEWANG
IX1

<---------创建一个xml文件,叫做a1.xml
a1.xml:
<?xml version="1.0" encoding="UTF-8"?>
<OPTPROFILE VERSION="9.1.0.0">
<STMTPROFILE ID="Use Table Scan instead of Index Scan">
<STMTKEY SCHEMA="TAOEWANG">
<![CDATA[SELECT * FROM TAOEWANG.MYTABLE WHERE ID < 1000]]>
</STMTKEY>
<OPTGUIDELINES>
<TBSCAN TABLE="TAOEWANG.MYTABLE"/>
</OPTGUIDELINES>
</STMTPROFILE>
</OPTPROFILE>

<----------创建一个del文件,叫insert.del
insert .del:
"TAOEWANG", "PROF1", "a1.xml"

<--------用import把xml插入profile系统表
D:TEMP>db2 import from insert.del of del modified by lobsinfile insert into systools.opt_profile
SQL3109N The utility is beginning to load data from file "insert.del".

SQL3110N The utility has completed processing. "1" rows were read from the
input file.

SQL3221W ...Begin COMMIT WORK. Input Record Count = "1".

SQL3222W ...COMMIT of any database changes was successful.

SQL3149N "1" rows were processed from the input file. "1" rows weresuccessfully inserted into the table. "0" rows were rejected.


Number of rows read = 1
Number of rows skipped = 0
Number of rows inserted = 1
Number of rows updated = 0
Number of rows rejected = 0
Number of rows committed = 1

<--------设置db2set env variable打开profile
D:TEMP>db2set DB2_OPTPROFILE=YES

<--------重起实例让db2set生效
D:TEMP>db2stop force
12/27/2007 08:54:45 0 0 SQL1064N DB2STOP processing was successful.
SQL1064N DB2STOP processing was successful.

D:TEMP>db2start
12/27/2007 08:54:48 0 0 SQL1063N DB2START processing was successful.
SQL1063N DB2START processing was successful.

D:TEMP>db2 connect to SAMPEL2

Database Connection Information

Database server = DB2/NT 9.1.0
SQL authorization ID = TAOEWANG
Local database alias = SAMPEL2


D:TEMP>db2 set current explain mode explain
DB20000I The SQL command completed successfully.

D:TEMP>db2 set current schema taoewang
DB20000I The SQL command completed successfully.

<---------设置需要使用的profile
D:TEMP>db2 set current optimization profile='PROF1'
DB20000I The SQL command completed successfully.

D:TEMP>db2 "SELECT * FROM TAOEWANG.MYTABLE WHERE ID < 1000"
SQL0217W The statement was not executed as only Explain information requests
are being processed. SQLSTATE=01604

D:TEMP>db2 set current explain mode no
DB20000I The SQL command completed successfully.

D:TEMP>db2exfmt -d sampel2 -g TIC -w -1 -n % -s % -# 0 -o output2.txt
DB2 Universal Database Version 9.1, 5622-044 (c) Copyright IBM Corp. 1991, 2006
Licensed Material - Program Property of IBM
IBM DATABASE 2 Explain Table Format Tool

Connecting to the Database.
Connect to Database Successful.
Output is in output2.txt.
Executing Connect Reset -- Connect Reset was Successful.

<------现在用了tablescan了
D:TEMP>uedit32 output2.txt
Profile Information:
--------------------
OPT_PROF: (Optimization Profile Name)
TAOEWANG.PROF1
STMTPROF: (Statement Profile Name)
Use Table Scan instead of Index Scan


Original Statement:
------------------
SELECT *
FROM TAOEWANG.MYTABLE
WHERE ID < 1000


Optimized Statement:
-------------------
SELECT Q1.NAME AS "NAME", Q1.ID AS "ID", Q1.SALARY AS "SALARY", Q1.PHONE AS
"PHONE"
FROM TAOEWANG.MYTABLE AS Q1
WHERE (Q1.ID < 1000)

Access Plan:
-----------
Total Cost: 7.56912
Query Degree: 1

Rows
RETURN
( 1)
Cost
I/O
|
1
TBSCAN
( 2)
7.56912
1
|
4
TABLE: TAOEWANG
MYTABLE




Extended Diagnostic Information:
--------------------------------

No extended Diagnostic Information for this statment.

如果用户希望在应用程序里面使用profile,可以使用下面的几种方法之一

对于cli应用程序中使用EXEC SQL SET CURRENT OPTIMIZATION PROFILE = 'xxxxxxxxx';
也可以在db2cli.ini中指定CURRENTOPTIMIZATIONPROFILE='"SCHEMA"."PROFILE"'
对于stored procedure在bind的时候指定OPTPROFILE

再次强调,profile不是万能药,只是止痛药~~~只有在万不得已的情况下才应该使用profile暂时指定用户需要的操作.一般来说,对于优化器问题用户应该尽量找到root cause,而不是简单地指定一个profile了事~~~

myfriend2010 发表于:2007.12.28 09:18 ::分类: ( db2 ) ::阅读:(226次) :: 评论 (17)
===========================================================
DB2表中统计信息收集及数据重组 转
===========================================================
DB2提供了3个命令工具,重组和分析table中的数据:
REORGCHK
REORG
RUNSTAT

在(一)中收集了对象的统计信息,这里,可以用这些统计信息来诊断对象的物理存储了。
具体内容见:http://blog.csdn.net/dlinger/archive/2004/10/12/133178.aspx

2.REORGCHK ,诊断对象的物理存储

>>-REORGCHK----+-------------------------------+----------------------------------+<<
| |-UPDATE--| | | .-USER------- .--|
'--+-CURRENT-+---STATISTICS--' '-ON TABLE--+-SYSTEM-----+--'
+-ALL--------+
'-table-name-'

在UDB的V8版本中增加了on schema 的选项。

UPDATE STATISTICS:先调用RUNSTATS来对table进行分析,
然后根据分析的统计信息诊断是否需要重组table
CURRENT STATISTICS:使用现有的统计信息诊断是否需要重组table

ON TABLE USER: 当前USER的所有table
ON TABLE SYSTEM:SYSTEM的所有table
ON TABLE ALL: 当前db的所有table
ON TABLE table-name:指定名称的table

我们分析SYSIBM.SYSTABLES,看看具体的执行结果:

db2 => reorgchk update statistics on table SYSIBM.SYSTABLES

执行 RUNSTATS ....

表统计信息:

F1: 100 * OVERFLOW / CARD < 5
F2: 100 * (Effective Space Utilization of Data Pages) > 70
F3: 100 * (Required Pages / Total Pages) > 80

SCHEMA NAME CARD OV NP FP ACTBLK TSIZE F1 F2 F3 REORG
----------------------------------------------------------------------------------------
SYSIBM SYSTABLES 2988 0 290 290 - 4774824 0 100 100 ---
----------------------------------------------------------------------------------------

索引统计信息:

F4: CLUSTERRATIO 或正常化的 CLUSTERFACTOR > 80
F5: 100 * (KEYS * (ISIZE + 9) + (CARD - KEYS) * 5) / ((NLEAF - NUM EMPTY LEAFS) * INDEXPAGESIZE) > 50
F6: (100 - PCTFREE) * ((INDEXPAGESIZE - 96) / (ISIZE + 12)) ** (NLEVELS - 2) * (INDEXPAGESIZE - 96)
/ (KEYS * (ISIZE + 9) + (CARD - KEYS) * 5) < 100
F7: 100 * (NUMRIDS DELETED / (NUMRIDS DELETED + CARD)) < 20
F8: 100 * (NUM EMPTY LEAFS / NLEAF) < 20

SCHEMA NAME CARD LEAF ELEAF LVLS ISIZE NDEL KEYS F4 F5 F6 F7 F8 REORG
-------------------------------------------------------------------------------------------------
表:SYSIBM.SYSTABLES
SYSIBM IBM00 2988 55 0 2 27 42 2988 95 47 3 1 0 -*---
SYSIBM IBM137 2988 18 0 2 4 52 2845 98 51 9 1 0 -----
SYSIBM IBM21 2988 5 0 2 3 26 3 99 73 24 0 0 -----
SYSIBM IBM22 2988 5 0 2 3 22 1 100 72 24 0 0 -----
SYSIBM IBM23 2988 5 0 2 3 2 1 100 72 24 0 0 -----
SYSIBM IBM78 2988 62 0 2 33 17 2988 95 49 2 0 0 -*---
-------------------------------------------------------------------------------------------------

CLUSTERRATIO 或正常化的 CLUSTERFACTOR(F4)将指示索引需要
REORG,该索引与基本表不在相同的序列中。当在表中定义了多个索引时,一个或多个索引
可能被标记为需要 REORG。指定 REORG 顺序的最重要索引。

使用 ORGANIZE BY 子句和相应的维索引定义的表的名称有 '*'
后缀。维索引的基数等价于表的“活动的块数”统计信息。


先来说明一下上面的信息:

CARD:基表中的数据行数
OV(OVERFLOW): 迁移行的数量
NP(NPAGES): 包含数据的page的数量
FP(FPAGES): 该表总共分配的page数量
TSIZE:table的实际数据的大小,以字节为单位。
TABLEPAGESIZE:table所在表空间的page size
F1: 处理溢出行。在溢出行超过总行数的5%时,该报告建议对table进行重组。
F2:处理空间使用率。在TSIZE小于等于该表分配总空间的70%时,该报告建议对table进行重组。
F3:处理空白页。所谓空白页,就是没有数据的页。当table中空白页大于20%时,该报告建议对table进行重组。

LEAF:index上叶节点的数量
LVLS(LEVELS):index级数
ISIZE:index的平均行长。
KEYS:唯一取值的数量
INDEXPAGESIZE:index所在表空间的page size
PCTFREE:index page中预留空间(%)
F4:聚簇因子
F5:为index key预留的空间。这个值应小于50%,否则该报告建议对index进行重组
F6:估算index页的用量,应大于总数的90%,否则该报告建议对index进行重组
F7:伪删除RID的数量。应小于总数的20%,否则该报告建议对index进行重组
F8: 伪空页的数量。应小于总数的20%,否则该报告建议对index进行重组


我们根据报告中REORG的值中有“*”来决定是否对table或index进行数据重组。当然,F1-F8的阀值只是建议值。


第三部分,我们将介绍在DB2中如何对数据进行重组。

myfriend2010 发表于:2007.12.18 21:12 ::分类: ( db2 ) ::阅读:(575次) :: 评论 (3)
===========================================================
SQL0290N 表空间状态为: 停顿的独占的处理
===========================================================
今天一个同事报告一个问题,表都不能使用了
检查了一下,发现
问题 db2 => select * from test

ACTNO ACTKWD ACTDESC
------ ------ --------------------
SQL0290N Table space access is not allowed. SQLSTATE=55039
其他表也不能使用

在db2cc里查看表空间状态为: 停顿的独占


解决方法:

到命令行状态,首先connect 到需要处理的数据库

1、db2 => list tablespaces show detail 显示表空间状态

Tablespaces for Current Database

Tablespace ID = 0
Name = SYSCATSPACE
Type = System managed space
Contents = Any data
State = 0x0000
Detailed explanation:
Normal
Total pages = 2519
Useable pages = 2519
Used pages = 2519
Free pages = Not applicable
High water mark (pages) = Not applicable
Page size (bytes) = 4096
Extent size (pages) = 32
Prefetch size (pages) = 32
Number of containers = 1

Tablespace ID = 1
Name = TEMPSPACE1
Type = System managed space
Contents = System Temporary data
State = 0x0000
Detailed explanation:
Normal
Total pages = 1
Useable pages = 1
Used pages = 1
Free pages = Not applicable
High water mark (pages) = Not applicable
Page size (bytes) = 4096
Extent size (pages) = 32
Prefetch size (pages) = 32
Number of containers = 1

Tablespace ID = 2
Name = USERSPACE1
Type = System managed space
Contents = Any data
State = 0x0004 这个代码意义就是“停顿的独占”,正常状态为0x0000,
非0就是有问题,都可以用下面方法解决。
Detailed explanation:
Quiesced: EXCLUSIVE
Total pages = 687
Useable pages = 687
Used pages = 687
Free pages = Not applicable
High water mark (pages) = Not applicable
Page size (bytes) = 4096
Extent size (pages) = 32
Prefetch size (pages) = 32
Number of containers = 1
Number of quiescers = 1 注意下面几行
Quiescer 1:
Tablespace ID = 2
Object ID = 50 “object id是造成死锁表的id”


2、db2 => select tabname from syscat.tables where tableid=50 通过所住的id号找出是哪个表

TABNAME
--------------------------------------------------------------------------------------------------------------------------------
SYSINDEXEXTENSIONPARMS
TEST 就是这个表

2 record(s) selected.


3、db2 => quiesce tablespaces for table test reset 执行该命令清除错误的状态
DB20000I The QUIESCE TABLESPACES command completed successfully.

4、重新select,问题解决

5、比较常见导致改种问题的原因是,非正常的中止正对表进行的操作,导致对表空间的使用没有正常的释放。

myfriend2010 发表于:2007.12.06 09:56 ::分类: ( db2 ) ::阅读:(1034次) :: 评论 (12)
===========================================================
db2执行计划显示工具介绍
===========================================================
db2执行计划显示工具介绍
db2有图形执行计划显示工具,如果没有图形环境,如unix主机,可以生成文本的
文件来显示执行计划
1.如果第一次执行,请先 connect to dbname,
执行db2 -tvf $HOME/sqllib/misc/EXPLAIN.DDL建立执行计划表
2.db2 set current explain mode explain
设置成解释模式,并不真正执行下面将发出的sql命令
3.db2 "select count(*) from staff"
执行你想要分析的sql语句
4.db2 set current explain mode no
取消解释模式
5.db2exfmt -d sample -g TIC -w -l -s % -n % -o db2exmt.out
执行计划输出到文件db2exmt.out
myfriend2010 发表于:2007.12.05 14:46 ::分类: ( db2 ) ::阅读:(199次) :: 评论 (1)
===========================================================
在DB2中恢复删除表的技巧-转
===========================================================

这边转载了一个恢复drop后的表的一个操作,类似于oracle 10g中的闪回!

DB2在历史文件中保存了备份,恢复,装载数据,删除表等操作.

假设数据库名为sample, 您可以用下面的命令列出删除表的记录: db2 "list history dropped table all for sample"

下一步是从以前的备份中恢复删除表所在的表空间, 备份所在的目录是c:db2backup.
without rolling forward指明不需要前滚.
db2 "restore db sample tablespace(userspace1) from c:db2backup taken at 20041102100931 without rolling forward without prompting"

第三步是把所删除表的数据卸载到某一目录中
db2 "rollforward db sample to end of logs and complete recover dropped table 00000000000002010002000d to c:db2backup"

第四步是用历史文件中保留的该表的DDL语句重建该表

第五步是重新装载数据到该表. p(1,2)表明装载该表的第一个和第二个字段的内容. recoverme是表名

db2 "load from c:db2backupnode0000data OF DEL METHOD p(1,2) insert into recoverme"


myfriend2010 发表于:2007.11.29 13:31 ::分类: ( db2 ) ::阅读:(175次) :: 评论 (5)
===========================================================
客户端查看数据库服务器端的锁信息
===========================================================

1.查看本地实例
C:>db2ilist
DB2

---本地实例为db2
2.查看当前正在使用的实例
C:>db2 get instance

当前数据库管理器实例是:DB2

3.查看节点编目情况,得到非本地的实例
C:>db2 list node directory

节点目录

目录中的条目数 = 1

节点 1 条目:

节点名 = DB164
注释 =
目录条目类型 = LOCAL
协议 = TCPIP
主机名 = 169.254.11.164
服务名称 = 50000


C:>db2 list node directory show detail

节点目录

目录中的条目数 = 1

节点 1 条目:

节点名 = DB164
注释 =
目录条目类型 = LOCAL
协议 = TCPIP
主机名 = 169.254.11.164
服务名称 = 50000
远程实例名 = db2
系统 =
操作系统类型 = 无

可以看到本地有169.254.11.164上的DB164实例的节点编目。

4.查看所有数据库和实例的对应信息。
C:>db2 list db directory

系统数据库目录

目录中的条目数 = 3

数据库 1 条目:

数据库别名 = DW
数据库名称 = DW
节点名 = DB164
数据库发行版级别 = a.00
注释 =
目录条目类型 = 远程
认证 = SERVER
目录数据库分区号 = -1
备用服务器主机名 =
备用服务器端口号 =

数据库 2 条目:

数据库别名 = CCP_BUSI
数据库名称 = CCP_BUSI
节点名 = DB164
数据库发行版级别 = a.00
注释 =
目录条目类型 = 远程
认证 = SERVER
目录数据库分区号 = -1
备用服务器主机名 =
备用服务器端口号 =

数据库 3 条目:

数据库别名 = MYDB
数据库名称 = MYDB
数据库驱动器 = D:DB2
数据库发行版级别 = a.00
注释 =
目录条目类型 = 间接
目录数据库分区号 = 0
备用服务器主机名 =
备用服务器端口号 =

---可以看到db164上有2个数据库DW和CCP_BUSI,下一步就连结到DW上看看

5.attach到db164上
C:>db2 attach to db164 user db2admin
输入 db2admin 的当前密码:

实例连接信息

实例服务器 = DB2/NT 8.2.0
授权标识 = DB2ADMIN
本地实例别名 = DB164

6. 查看db164上的锁信息
C:>
C:>db2 get snapshot for locks on dw

数据库锁定快照

数据库名称 = DW
数据库路径 = F:DB2NODE0000SQL00001
输入数据库别名 = DW
挂起的锁定 = 0
当前已连接的应用程序 = 6
当前正等待锁定的代理进程数 = 0
快照时间戳记 = 2007-11-21 16:06:10.510838

应用程序句柄 = 395
应用程序标识 = A9FE0B84.O009.0465C1073117
序号 = 0008
应用程序名 = QuestCentral.exe
CONNECT 授权标识 = CCP
应用程序状态 = UOW 正在等待
状态更改时间 = 未收集
应用程序代码页 = 1386
挂起的锁定 = 0
总计等待时间(毫秒) = 未收集


应用程序句柄 = 336
应用程序标识 = A9FE0BA6.I708.071121064255
序号 = 0004
应用程序名 = QuestCentral.exe
CONNECT 授权标识 = CCP
应用程序状态 = UOW 正在等待
状态更改时间 = 未收集
应用程序代码页 = 1386
挂起的锁定 = 0
总计等待时间(毫秒) = 未收集


应用程序句柄 = 280
应用程序标识 = A9FE0BA6.N806.071121031820
序号 = 0011
应用程序名 = QuestCentral.exe
CONNECT 授权标识 = CCP
应用程序状态 = UOW 正在等待
状态更改时间 = 未收集
应用程序代码页 = 1386
挂起的锁定 = 0
总计等待时间(毫秒) = 未收集


应用程序句柄 = 95
应用程序标识 = A9FE0B86.NA06.015D01013815
序号 = 0042
应用程序名 = QuestCentral.exe
CONNECT 授权标识 = CCP
应用程序状态 = UOW 正在等待
状态更改时间 = 未收集
应用程序代码页 = 1386
挂起的锁定 = 0
总计等待时间(毫秒) = 未收集


应用程序句柄 = 62
应用程序标识 = A9FE0BA6.MF05.071121013410
序号 = 0005
应用程序名 = QuestCentral.exe
CONNECT 授权标识 = CCP
应用程序状态 = UOW 正在等待
状态更改时间 = 未收集
应用程序代码页 = 1386
挂起的锁定 = 0
总计等待时间(毫秒) = 未收集


应用程序句柄 = 54
应用程序标识 = A9FE0BA6.M305.071121013157
序号 = 0008
应用程序名 = QuestCentral.exe
CONNECT 授权标识 = CCP
应用程序状态 = UOW 正在等待
状态更改时间 = 未收集
应用程序代码页 = 1386
挂起的锁定 = 0
总计等待时间(毫秒) = 未收集


myfriend2010 发表于:2007.11.21 16:56 ::分类: ( db2 ) ::阅读:(241次) :: 评论 (0)
===========================================================
IP转换的函数!
===========================================================

在数据库的开发和管理过程中,时常用到需要查询链接对应的IP地址!
一般都是用这个命令db2 list applications,但是db2的这个命令有一个不合理的地方,就是他显示IP是以16进制的形式,
所以通常需要把进程对应的“应用程序标识”的小数点前的那个字符串,转换成10进制的数来检查IP。

于是乎我写了一个小过程,可以把那个字符串直接转换成ip地址的形式,不敢独享,现公布给大家。

程序如下:

-- Start of generated script for 169.254.11.164-db2-DW (ccp)
-- Nov-15-2007 at 17:35:12
drop PROCEDURE CCP.GETIP;
SET SCHEMA CCP ;

SET CURRENT PATH = "SYSIBM","SYSFUN","SYSPROC","CCP";

CREATE PROCEDURE CCP.GETIP
(IN I_IP VARCHAR(8),
OUT O_IP VARCHAR(20)
)
LANGUAGE SQL
NOT DETERMINISTIC
CALLED ON NULL INPUT
EXTERNAL ACTION
OLD SAVEPOINT LEVEL
MODIFIES SQL DATA
INHERIT SPECIAL REGISTERS
begin
/*
--auther:Z.X.T
--DATE:2007-11-15
--描述,本过程可以把16进制的IP转换成一般的IP形式
--I_IP 输入:长度为8的16进制数,如'AABBCCDD'
--O_IP 输出:ip地址形式如:192.168.1.0
*/
declare first_IP1 varchar(3);
declare first_IP2 varchar(3);
declare first_IP3 varchar(3);
declare first_IP4 varchar(3);
declare first_IP11 INTEGER;
declare first_IP21 INTEGER;
declare first_IP31 INTEGER;
declare first_IP41 INTEGER;
if(I_IP='*N0') then
set O_IP ='本地';
return;
end if;
if(length(I_IP)!=8) then
set O_IP ='输入错误';
return;
end if;
set first_IP1=Ucase(substr(I_IP,1,2));
set first_IP2=Ucase(substr(I_IP,3,2));
set first_IP3=Ucase(substr(I_IP,5,2));
set first_IP4=Ucase(substr(I_IP,7,2));
set first_IP11=INTEGER(case substr(first_IP1,1,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP1,1,1) end)*16
+INTEGER(case substr(first_IP1,2,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP1,2,1) end);


set first_IP21=INTEGER(case substr(first_IP2,1,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP2,1,1) end
)*16
+INTEGER(case substr(first_IP2,2,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP2,2,1) end);


set first_IP31=INTEGER(case substr(first_IP3,1,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP3,1,1) end
)*16
+INTEGER(case substr(first_IP3,2,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP3,2,1) end);

set first_IP41=INTEGER(case substr(first_IP4,1,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP4,1,1) end
)*16
+INTEGER(case substr(first_IP4,2,1) when 'A' then '10' when 'B' then '11' when 'C' then '12'
when 'D' then '13' when 'E' then '14' when 'F' then '15'
when 'G' then '0' else substr(first_IP4,2,1) end);

set O_IP=rtrim(char(first_IP11))||'.'||rtrim(char(first_IP21))||'.'||rtrim(char(first_IP31))||'.'||Rtrim(char(first_IP41));
end;

#SYNC 10;
commit;

-- End of generated script for 169.254.11.164-db2-DW (ccp)

ok,存储过程完成!下来测试下看看!


C:>db2 list applications

授权标识 应用程序名 应用程序 应用程序标识 DB 代理进程
句柄 名称 序号
-------- -------------- ---------- ------------------------------ -------- -----
CCP db2bp.exe 341 A9FE0B84.G710.033705103339 DW 1
CCP QuestCentral.e 325 A9FE0B84.G510.00F5C5102039 DW 1
CCP QuestCentral.e 323 A9FE0B84.G410.00F5C5102026 DW 1
CCP QuestCentral.e 302 A9FE0B84.C10F.00F5C5100723 DW 1
CCP QuestCentral.e 262 A9FE0B84.I50F.00F5C5093513 DW 1
CCP QuestCentral.e 258 A9FE0B84.I20F.00F5C5093332 DW 1
CCP QuestCentral.e 186 A9FE0B84.LF0E.00F5C5084450 DW 1
CCP clemlocal.exe 178 A9FE0BA6.B007.071115083616 DW 7
CCP QuestCentral.e 82 A9FE0B84.AE0C.00F5C5082400 DW 3
TEST db2jccWebConta 329 A9FE0B9E.F181.071115102030 CCP_BUSI 12
TEST QuestCentral.e 320 A9FE0B88.N00C.019845101725 CCP_BUSI 2
TEST QuestCentral.e 318 A9FE0B88.MD0C.019845101711 CCP_BUSI 1
TEST db2jccWebConta 317 A9FE0B9E.F081.071115101401 CCP_BUSI 11
TEST QuestCentral.e 313 A9FE0B88.G20C.019845101424 CCP_BUSI 1
TEST QuestCentral.e 309 A9FE0B88.F10B.019845101203 CCP_BUSI 1
TEST QuestCentral.e 306 A9FE0B88.E20B.019845100938 CCP_BUSI 3
TEST QuestCentral.e 298 A9FE0B88.A90B.019845100509 CCP_BUSI 10


C:>db2 list applications

授权标识 应用程序名 应用程序 应用程序标识 DB 代理进程
句柄 名称 序号
-------- -------------- ---------- ------------------------------ -------- -----
CCP db2bp.exe 341 A9FE0B84.G710.033705103339 DW 1
CCP QuestCentral.e 325 A9FE0B84.G510.00F5C5102039 DW 1
CCP QuestCentral.e 323 A9FE0B84.G410.00F5C5102026 DW 1
CCP QuestCentral.e 302 A9FE0B84.C10F.00F5C5100723 DW 1
CCP QuestCentral.e 262 A9FE0B84.I50F.00F5C5093513 DW 1
CCP QuestCentral.e 258 A9FE0B84.I20F.00F5C5093332 DW 1
CCP QuestCentral.e 186 A9FE0B84.LF0E.00F5C5084450 DW 1
CCP clemlocal.exe 178 A9FE0BA6.B007.071115083616 DW 7
CCP QuestCentral.e 82 A9FE0B84.AE0C.00F5C5082400 DW 3
TEST db2jccWebConta 329 A9FE0B9E.F181.071115102030 CCP_BUSI 13
TEST QuestCentral.e 320 A9FE0B88.N00C.019845101725 CCP_BUSI 2
TEST QuestCentral.e 318 A9FE0B88.MD0C.019845101711 CCP_BUSI 1
TEST QuestCentral.e 313 A9FE0B88.G20C.019845101424 CCP_BUSI 1
TEST QuestCentral.e 309 A9FE0B88.F10B.019845101203 CCP_BUSI 1
TEST QuestCentral.e 306 A9FE0B88.E20B.019845100938 CCP_BUSI 3
TEST QuestCentral.e 298 A9FE0B88.A90B.019845100509 CCP_BUSI 10


C:>db2 connect to dw

数据库连接信息

数据库服务器 = DB2/NT 8.2.0
SQL 授权标识 = DB2ADMIN
本地数据库别名 = DW


C:>db2 call CCP.GETIP('A9FE0B88',?)

输出参数的值
--------------------------
参数名: O_IP
参数值: 169.254.11.136

返回状态 = 0


C:>


myfriend2010 发表于:2007.11.16 15:02 ::分类: ( db2 ) ::阅读:(215次) :: 评论 (0)
===========================================================
DB2改服务器名字过程
===========================================================


1.停止事例和数据库
db2stop
db2admin stop
2.改计算机名字并重启
原来为ZXT
修改为ZXTZ
重启
3.修改IBMSQLLIBDB2下的db2nodes.cfg
原来为
0 zxt ZXT 0
1 zxt ZXT 1

修改为
0 zxtz ZXT 0
1 zxtz ZXT 1
4.修改注册信息
C:>db2set db2system
ZXT
修改为

C:>db2set -g db2system=ZXTZ

5.uncatalog 本地node
C:>db2 list admin node directory show detail

节点目录

目录中的条目数 = 1

节点 1 条目:

节点名 = ZXT
注释 =
目录条目类型 = LOCAL
协议 = TCPIP
主机名 = ZXT
服务名称 = 523
远程实例名 =
系统 = ZXT
操作系统类型 = 无

C:>db2 uncatalog node zxt
DB20000I UNCATALOG NODE 命令成功完成。
DB21056W 只有在刷新目录高速缓存以后,目录更改才会生效。
6.catalog 本地node
C:>db2 catalog admin tcpip node ZXTZ remote ZXTZ system ZXTZ
DB20000I CATALOG ADMIN TCPIP NODE 命令成功完成。
DB21056W 只有在刷新目录高速缓存以后,目录更改才会生效。

C:>db2 update admin cfg using DB2SYSTEM ZXTZ
DB20000I UPDATE ADMIN CONFIGURATION 命令成功完成。

C:>db2 update admin cfg using SMTP_SERVER ZXTZ
DB20000I UPDATE ADMIN CONFIGURATION 命令成功完成。

7.启动数据库
C:>db2admin start
SQL4406W 已成功启动“DB2 管理服务器”。

C:>db2start
2007-11-14 15:42:50 1 0 SQL1063N DB2START 处理成功。
2007-11-14 15:42:51 0 0 SQL1063N DB2START 处理成功。
SQL1063N DB2START 处理成功。

C:>db2 connect to mydb

数据库连接信息

数据库服务器 = DB2/NT 8.2.0
SQL 授权标识 = ADMINIST...
本地数据库别名 = MYDB


myfriend2010 发表于:2007.11.16 15:00 ::分类: ( db2 ) ::阅读:(248次) :: 评论 (0)
===========================================================
DB2中有关日期和时间的函数,及应用--转
===========================================================
DAYNAME 返回一个大小写混合的字符串,对于参数的日部分,用星期表示这一天的名称(例如,Friday)。
DAYOFWEEK 返回参数中的星期几,用范围在 1-7 的整数值表示,其中 1 代表星期日。
DAYOFWEEK_ISO 返回参数中的星期几,用范围在 1-7 的整数值表示,其中 1 代表星期一。
DAYOFYEAR 返回参数中一年中的第几天,用范围在 1-366 的整数值表示。
DAYS 返回日期的整数表示。
JULIAN_DAY 返回从公元前 4712 年 1 月 1 日(儒略日历的开始日期)到参数中指定日期值之间的天数,用整数值表示。
MIDNIGHT_SECONDS 返回午夜和参数中指定的时间值之间的秒数,用范围在 0 到 86400 之间的整数值表示。
MONTHNAME 对于参数的月部分的月份,返回一个大小写混合的字符串(例如,January)。
TIMESTAMP_ISO 根据日期、时间或时间戳记参数而返回一个时间戳记值。
TIMESTAMP_FORMAT 从已使用字符模板解释的字符串返回时间戳记。
TIMESTAMPDIFF 根据两个时间戳记之间的时差,返回由第一个参数定义的类型表示的估计时差。
TO_CHAR 返回已用字符模板进行格式化的时间戳记的字符表示。TO_CHAR 是 VARCHAR_FORMAT 的同义词。
TO_DATE 从已使用字符模板解释过的字符串返回时间戳记。TO_DATE 是 TIMESTAMP_FORMAT 的同义词。
WEEK 返回参数中一年的第几周,用范围在 1-54 的整数值表示。以星期日作为一周的开始。
WEEK_ISO 返回参数中一年的第几周,用范围在 1-53 的整数值表示。

要使当前时间或当前时间戳记调整到 GMT/CUT,则把当前的时间或时间戳记减去当前时区寄存器:
current time - current timezone
current timestamp - current timezone

给定了日期、时间或时间戳记,则使用适当的函数可以单独抽取出(如果适用的话)年、月、日、时、分、秒及微秒各部分:
YEAR (current timestamp)
MONTH (current timestamp)
DAY (current timestamp)
HOUR (current timestamp)
MINUTE (current timestamp)
SECOND (current timestamp)
MICROSECOND (current timestamp)

因为没有更好的术语,所以您还可以使用英语来执行日期和时间计算:
current date + 1 YEAR
current date + 3 YEARS + 2 MONTHS + 15 DAYS
current time + 5 HOURS - 3 MINUTES + 10 SECONDS

从时间戳记单独抽取出日期和时间也非常简单:
DATE (current timestamp)
TIME (current timestamp)

而以下示例描述了如何获得微秒部分归零的当前时间戳记:

CURRENT TIMESTAMP - MICROSECOND (current timestamp) MICROSECONDS

如果想将日期或时间值与其它文本相衔接,那么需要先将该值转换成字符串。为此,只要使用 CHAR() 函数:

char(current date)
char(current time)
char(current date + 12 hours)

要将字符串转换成日期或时间值,可以使用:

TIMESTAMP ('2002-10-20-12.00.00.000000')
TIMESTAMP ('2002-10-20 12:00:00')
DATE ('2002-10-20')
DATE ('10/20/2002')
TIME ('12:00:00')
TIME ('12.00.00')

TIMESTAMP()、DATE() 和 TIME() 函数接受更多种格式。上面几种格式只是示例,我将把它作为一个练习,让读者自己去发现其它格式。

有时,您需要知道两个时间戳记之间的时差。为此,DB2 提供了一个名为 TIMESTAMPDIFF() 的内置函数。但该函数返回的是近似值,因为它不考虑闰年,而且假设每个月只有 30 天。以下示例描述了如何得到两个日期的近似时差:

timestampdiff (<n>, char(
timestamp('2002-11-30-00.00.00')-
timestamp('2002-11-08-00.00.00')))

对于 <n>,可以使用以下各值来替代,以指出结果的时间单位:

1 = 秒的小数部分
2 = 秒
4 = 分
8 = 时
16 = 天
32 = 周
64 = 月
128 = 季度
256 = 年
当日期很接近时使用 timestampdiff() 比日期相差很大时精确。如果需要进行更精确的计算,可以使用以下方法来确定时差(按秒计):

(DAYS(t1) - DAYS(t2)) * 86400 +
(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))

为方便起见,还可以对上面的方法创建 SQL 用户定义的函数:

CREATE FUNCTION secondsdiff(t1 TIMESTAMP, t2 TIMESTAMP)
RETURNS INT
RETURN (
(DAYS(t1) - DAYS(t2)) * 86400 +
(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))
)
@

如果需要确定给定年份是否是闰年,以下是一个很有用的 SQL 函数,您可以创建它来确定给定年份的天数:

CREATE FUNCTION daysinyear(yr INT)
RETURNS INT
RETURN (CASE (mod(yr, 400)) WHEN 0 THEN 366 ELSE
CASE (mod(yr, 4)) WHEN 0 THEN
CASE (mod(yr, 100)) WHEN 0 THEN 365 ELSE 366 END
ELSE 365 END
END)@

最后,以下是一张用于日期操作的内置函数表。它旨在帮助您快速确定可能满足您要求的函数,但未提供完整的参考。有关这些函数的更多信息,请参考 SQL 参考大全。

SQL 日期和时间函数
DAYNAME 返回一个大小写混合的字符串,对于参数的日部分,用星期表示这一天的名称(例如,Friday)。
DAYOFWEEK 返回参数中的星期几,用范围在 1-7 的整数值表示,其中 1 代表星期日。
DAYOFWEEK_ISO 返回参数中的星期几,用范围在 1-7 的整数值表示,其中 1 代表星期一。
DAYOFYEAR 返回参数中一年中的第几天,用范围在 1-366 的整数值表示。
DAYS 返回日期的整数表示。
JULIAN_DAY 返回从公元前 4712 年 1 月 1 日(儒略日历的开始日期)到参数中指定日期值之间的天数,用整数值表示。
MIDNIGHT_SECONDS 返回午夜和参数中指定的时间值之间的秒数,用范围在 0 到 86400 之间的整数值表示。
MONTHNAME 对于参数的月部分的月份,返回一个大小写混合的字符串(例如,January)。
TIMESTAMP_ISO 根据日期、时间或时间戳记参数而返回一个时间戳记值。
TIMESTAMP_FORMAT 从已使用字符模板解释的字符串返回时间戳记。
TIMESTAMPDIFF 根据两个时间戳记之间的时差,返回由第一个参数定义的类型表示的估计时差。
TO_CHAR 返回已用字符模板进行格式化的时间戳记的字符表示。TO_CHAR 是 VARCHAR_FORMAT 的同义词。
TO_DATE 从已使用字符模板解释过的字符串返回时间戳记。TO_DATE 是 TIMESTAMP_FORMAT 的同义词。
WEEK 返回参数中一年的第几周,用范围在 1-54 的整数值表示。以星期日作为一周的开始。
WEEK_ISO 返回参数中一年的第几周,用范围在 1-53 的整数值表示。
myfriend2010 发表于:2007.11.12 11:09 ::分类: ( db2 ) ::阅读:(223次) :: 评论 (0)
===========================================================
DB2锁介绍[转]
===========================================================

1 DB2 多粒度封锁机制介绍
1.1 锁的对象
DB2支持对表空间、表、行和索引加锁(大型机上的数据库还可以支持对数据页加锁)来保证数据库的并发完整性。不过在考虑用户应用程序的并发性的问题上,通常并不检查用于表空间和索引的锁。该类问题分析的焦点在于表锁和行锁。
1.2 锁的策略
DB2可以只对表进行加锁,也可以对表和表中的行进行加锁。如果只对表进行加锁,则表中所有的行都受到同等程度的影响。如果加锁的范围针对于表及下属的行,则在对表加锁后,相应的数据行上还要加锁。究竟应用程序是对表加行锁还是同时加表锁和行锁,是由应用程序执行的命令和系统的隔离级别确定。
1.2.1 DB2表锁的模式
DB2在表一级加锁可以使用以下加锁方式:
名称缩写 全名 描述
IN 无意图锁 (Intenet None)
不需要行锁 该锁的拥有者可以读表中的任何数据,包括其他事务尚未提交的数据,但不能对表中的数据进行更改。
IS 意图共享锁(Intent Share)需要行锁配合 该锁的拥有者在拥有相应行的上的S锁时可以读取该行的数据。但不能对表中的数据进行更改。
IX 意图排它锁(Intent eXclusive)需要行锁配合 该锁的拥有者在拥有相应行的X锁时可以更改该行的数据。
SIX 共享携意图排它锁
(Share with Intent exclusive)需要行锁配合 锁的拥有者可以读表中的任何数据,如果在相应的行上能够获得X锁,则可以修改该行。SIX锁的获得比较特殊,它是在应用程序已经拥有IX锁的情况下请求S锁或者是在应用程序已经拥有S锁的情况下请求IX锁时生成的。
S 共享锁(Share)不需要行锁配合 锁的拥有者可以读表中的任何数据,如果表上被加上S锁,该表中的数据就只能被读取,不能被改变。
U 更新锁(Update)
不需要行锁配合 锁的拥有者可以读表中的任何数据,如果在升级到X锁之后,可以更改表中的任何数据。该锁是处于等待对数据进行更改的一种中间状态。
X 排它锁
(eXclusive)
不需要行锁配合 锁的拥有者可以读取或更改表中的任何数据。如果对表加上X锁,除了未提交读程序,其他应用程序都不能对该表进行存取。
Z 超级排它锁
(Super Exclusive)
不需要行锁配合 该锁不是通过应用程序中的DML语言来生成的。一般是通过对表进行删除(Drop)和转换(Alter)操作或创建和删除索引而获得的。如果对表上加上Z锁,其他应用程序,包括未提交读程序都不能对该表进行存取。
表三:DB2数据库表锁的模式
下面对几种表锁的模式进一步加以阐述:
IS、IX、SIX方式用于表一级并需要行锁配合,他们可以阻止其他应用程序对该表加上排它锁。
 如果一个应用程序获得某表的IS锁,该应用程序可获得某一行上的S锁,用于只读操作,同时其他应用程序也可以读取该行,或是对表中的其他行进行更改。
 如果一个应用程序获得某表的IX锁,该应用程序可获得某一行上的X锁,用于更改操作,同时其他应用程序可以读取或更改表中的其他行。
 如果一个应用程序获得某表的SIX锁,该应用程序可以获得某一行上的X锁,用于更改操作,同时其他应用程序只能对表中其他行进行只读操作。
S、U、X和Z方式用于表一级,但并不需要行锁配合,是比较严格的表加锁策略。
 如果一个应用程序得到某表的S锁。该应用程序可以读表中的任何数据。同时它允许其他应用程序获得该表上的只读请求锁。如果有应用程序需要更改读该表上的数据,必须等S锁被释放。
 如果一个应用程序得到某表的U锁,该应用程序可以读表中的任何数据,并最终可以通过获得表上的X锁来得到对表中任何数据的修改权。其他应用程序只能读取该表中的数据。U锁与S锁的区别主要在于更改的意图上。U锁的设计主要是为了避免两个应用程序在拥有S锁的情况下同时申请X锁而造成死锁的。
 如果一个应用程序得到某表上的X锁,该应用程序可以读或修改表中的任何数据。其他应用程序不能对该表进行读或者更改操作。
 如果一个应用程序得到某表上的Z锁,该应用程序可以读或修改表中的任何数据。其他应用程序,包括未提交读程序都不能对该表进行读或者更改操作。
IN锁用于表上以允许未提交读这一概念。
1.2.2 DB2行锁的模式
除了表锁之外,DB2还支持以下几种方式的行锁。
名称缩写 全名 需要表锁的最低级别 描述
S 共享锁
(Share) IS 该行正在被某个应用程序读取,其他应用程序只能对该行进行读操作。
U 更改锁
(Update) IX 某个应用程序正在读该行并有可能更改该行,其他应用程序只能读该行。
X 排它锁
(eXclusive) IX 该行正在被某个应用程序更改,其他应用程序不能访问该行。
W 弱排它锁
(Weak eXclusive) IX 当一行数据被插入表中的时候,该行上会被加上W锁。锁的拥有者能够更改该行,该锁基本与X锁相同,除了它与NW锁兼容。
NS 下一键共享锁
(Next Key Share) IS 锁的拥有者和其他程序都可以读该行,但不能对该行进行更改。当应用程序处于RS或CS隔离级下,该锁用来替代S锁。
NX 下一键排它锁
(Next Key eXclusive) IX 当一行数据被插入到索引中或从索引中被删除的时候,该行的下一行上会被加上该锁。锁的拥有者可以读,但不能更改锁定行。该锁与X锁类似,只是与NS锁兼容。
NW 下一键弱排它锁
(Next Key Weak eXclusive) IX 当一行被插入到索引中的时候,该行的下一行会被加上该锁。锁的拥有者可以读但不能更改锁定行。该锁与X和NX锁类似,只是与W和NS锁兼容。
表四:DB2数据库行锁的模式
DB2锁的兼容性

锁A的模式 锁B的模式
IN IS S IX SIX U X Z
IN Y Y Y Y Y Y Y N
IS Y Y Y Y Y Y N N
S Y Y Y N N Y N N
IX Y Y N Y N N N N
SIX Y Y N N N N N N
U Y Y Y N N N N N
X Y N N N N N N N
Z N N N N N N N N
表五:DB2数据库表锁的相容矩阵
锁A的模式 锁B的模式
S U X W NS NX NW
S Y Y N N Y N N
U Y N N N Y N N
X N N N N N N N
W N N N N N N Y
NS Y Y N N Y Y Y
NX N N N N Y N N
NW N N N Y Y N N
表六:DB2数据库行锁的相容矩阵
下表是笔者总结了DB2中各SQL语句产生表锁的情况(假设缺省的隔离级别为CS):
SQL语句 行锁
模式 表锁
模式 允许的锁模式
Select * from table_name for read only with rr.. 无 S IN,IS,S,U
Select * from table_name for read only with rs.. NS IS IN,IS,S,SIX,U
Select * from table_name for read only with cs.. 无 无
Select * from table_name for read only with ur.. 无 无
Select * from table_name for update with rr 无 U IN,IS,S
Select * from table_name for update with rs U IX IN,IS,IX
Select * from table_name for update with cs U IX IN,IS,IX
Select * from table_name for update with ur U IX IN,IS,IX
Insert into table_name…… W IX IN,IS,IX
Update table_name…… X IX IN,IS,IX
Delete from table_name…… X IX IN,IS,IX
lock table table_name in share mode 无 S IN,IS,S,U
lock table table_name in exclusive mode 无 X IN
Alter table t1 add column id int Z
Drop table t1 X Z
Create table t1(id int) Z
注:alter,create,drop会在syscolumns,systables,systablespaces,sysuserath等数据字典系统表中加行级锁。
1.3 DB2锁的升级
每个锁在内存中都需要一定的内存空间,为了减少锁需要的内存开销,DB2提供了锁升级的功能。锁升级是通过对表加上非意图性的表锁,同时释放行锁来减少锁的数目,从而达到减少锁需要的内存开销的目的。锁升级是由数据库管理器自动完成的,有两个数据库的配置参数直接影响锁升级的处理:
locklist—在一个数据库全局内存中用于锁存储的内存。单位为页(4K)。
maxlocks—一个应用程序允许得到的锁占用的内存所占locklist大小的百分比。
锁升级会在这两种情况下被触发:
 某个应用程序请求的锁所占用的内存空间超出了maxlocks与locklist的乘积大小。这时,数据库管理器将试图通过为提出锁请求的应用程序申请表锁,并释放行锁来节省空间。
 在一个数据库中已被加上的全部锁所占的内存空间超出了locklist定义的大小。这时,数据库管理器也将试图通过为提出锁请求的应用程序申请表锁,并释放行锁来节省空间。
锁升级是有可能会失败的,比如,现在一个应用程序已经在一个表上加有IX锁,表中的某些行上加有X锁,另一个应用程序又来请求表上的IS锁,以及很多行上的S锁,由于申请的锁数目过多引起锁的升级。数据库管理器试图为该应用程序申请表上的S锁来减少所需要的锁的数目,但S锁与表上原有的IX锁冲突,锁升级不能成功。
如果锁升级失败,引起锁升级的应用程序将接到一个-912的SQLCODE。

myfriend2010 发表于:2007.11.08 17:26 ::分类: ( db2 ) ::阅读:(316次) :: 评论 (0)
===========================================================
如何降低DB2的管理表空间的高水位标记
===========================================================


本文介绍如何通过使用 DB2DART 工具降低 DB2 数据库管理表空间的高水位标记。


对于 DB2 数据库管理(DMS)表空间的高水位标记(HWM)是指该表空间曾经使用到的最大数据页数。如果使用:

db2 list tablespaces show detail

看到某个 DMS 表空间的已用页数低于高水位标记,则有可能通过如下方法降低高水位标记:

1、重组表空间的某个表;

2、将某个表中的数据导出,然后将它删除,重新创建该表再将数据导入。


在以上的方法中,首先要找到持有高水位标记的那个表,这可通过 DB2DART 命令(在停止实例后方可使用)加上 /DHWM 选项,提供表空间标识,然后从命令所产生的报告文件中获得。


而要了解通过对该表进行哪些操作可降低 HWM 的建议,可使用 DB2DART 加上 /LHWM 选项,从产生的报告文件中获得。使用 /LHWM 选项时,要求用户给出表空间的标识以及希望 HWM 降低到的页数(虽然不能保证 HWM 一定能降低到这一用户期望值),如果该值使用 0,则表明由 DB2 将 HWM 降低到能够达到的最低值。


另外还可利用 DB2DART 加 /RHWM 选项来移去 DMS 表空间中不再需要的空间映射数据块来降低 HWM,这些空间映射数据块在其映射的数据被删除时是不会被删除的

附:db2dart 使用方法

1.db2dart xx /db (xx为数据库名)

2.db2dart xx /DHWM /RPT c: (需要根据提示输入表空间号)

3.db2dart xx /RHWM(需要根据提示输入表空间号)


myfriend2010 发表于:2007.11.03 11:40 ::分类: ( db2 ) ::阅读:(211次) :: 评论 (8)
===========================================================
Windows上DB2 UDB脚本编制简介3
===========================================================
收集 DB2 系统信息

另一个可以用 Windows shell 和 DB2 命令迅速进行脚本编制的任务是相关系统、实例和数据库信息的收集。我们可以收集系统资源、DB2 注册表变量、实例和数据库配置参数以及数据库资源利用情况的快照。在开始对数据库系统作出更改之前,有这样一个脚本始终是很方便的。

清单 9. DB2 获取配置信息的脚本(db2getconf.bat)


@echo off
::---------------------------------------------------------------------------::
:: This is a Windows Shell Script to collect DB2 system information. The
:: information collected is stored in a file name with the following format:
:: <instance>.<database>.YYYYMMDD.HHMMSS.rpt 
::---------------------------------------------------------------------------::
set script_name=%~n0
set script_log=%~n0.log
set script_ver=1.0
set DB2INSTANCE=DB2
set DB2DATABASE=SAMPLE

title %script_name% v%script_ver%
echo %script_name% v%script_ver% started on %date% at %time%

::---------------------------------------------------------------------------::
:: Set Script Date Variable
::---------------------------------------------------------------------------::
for /F "tokens=1-4 delims=/ " %%i in ('echo %date%') do (
    set script_date=%%l%%j%%k
    )

::---------------------------------------------------------------------------::
:: Set Script Time Variable
::---------------------------------------------------------------------------::
for /F "tokens=1-4 delims=:. " %%i in ('echo %time%') do (
    set script_time=%%i%%j%%k
    )

::---------------------------------------------------------------------------::
:: Set Script Report File
::---------------------------------------------------------------------------::
set script_rpt=%db2instance%.%db2database%.%script_date%.%script_time%.rpt

::---------------------------------------------------------------------------::
:: Collect DB2 Services Configuration (Requires Windows Resource Kit)
::---------------------------------------------------------------------------::
echo %script_name% v%script_ver% collecting DB2 Services configuration...
echo DB2 Services Configuration > %script_rpt%
srvinfo | find "DB2" >> %script_rpt% 2> %script_log%
if not %errorlevel% == 0 (
   echo ERROR: Unable to collect DB2 Services data, RC=%errorlevel%
   type %script_log%
   )

::---------------------------------------------------------------------------::
:: Collect DB2 Registry Configuration
::---------------------------------------------------------------------------::
echo %script_name% v%script_ver% collecting DB2 Registry configuration...
echo DB2 Registry Configuration >> %script_rpt%
db2set -all >> %script_rpt% 2> %script_log%
if not %errorlevel% == 0 (
   echo ERROR: Unable to collect DB2 Registry data, RC=%errorlevel%
   type %script_log%
   )

::---------------------------------------------------------------------------::
:: Collect DB2 Database Administration Server (DB2DAS00) Configuration
::---------------------------------------------------------------------------::
echo %script_name% v%script_ver% collecting DB2DAS00 instance configuration...
db2 get admin cfg >> %script_rpt% 2> %script_log%
if not %errorlevel% == 0 (
   echo ERROR: Unable to collect DB2DAS00 instance data, RC=%errorlevel%
   type %script_log%
   )

::---------------------------------------------------------------------------::
:: Collect DB2 Instance Configuration
::---------------------------------------------------------------------------::
echo %script_name% v%script_ver% collecting %DB2INSTANCE% instance 
configuration...
db2 get dbm cfg >> %script_rpt% 2> %script_log%
if not %errorlevel% == 0 (
   echo ERROR: Unable to collect %DB2INSTANCE% instance data, RC=%errorlevel%
   type %script_log%
   )

::---------------------------------------------------------------------------::
:: Collect DB2 Database Configuration
::---------------------------------------------------------------------------::
echo %script_name% v%script_ver% collecting %DB2DATABASE% database 
configuration...
db2 get db cfg for sample >> %script_rpt% 2> %script_log%
if not %errorlevel% == 0 (
   echo ERROR: Unable to collect %DB2DATABASE% database data, RC=%errorlevel%
   type %script_log%
   )

db2 connect to %DB2DATABASE%
if not %errorlevel% == 0 (
   echo ERROR: Unable to connect to %DB2DATABASE% database, RC=%errorlevel%
   type %script_log%
   )

db2 "select BUFFERPOOLID, BPNAME, NPAGES from SYSCAT.BUFFERPOOLS" >> 
%script_rpt% 2> %script_log%
if not %errorlevel% == 0 (
   echo ERROR: Unable to collect %DB2DATABASE% database bufferpool data, 
RC=%errorlevel%
   type %script_log%
   )

db2 list tablespaces show detail >> %script_rpt% 2> %script_log%
if not %errorlevel% == 0 (
   echo ERROR: Unable to collect %DB2DATABASE% database tablespace data, 
RC=%errorlevel%
   type %script_log%
   )

db2 connect reset
if not %errorlevel% == 0 (
   echo ERROR: Unable to reset connection from %DB2DATABASE% database, 
RC=%errorlevel%
   type %script_log%
   )

echo %script_name% v%script_ver% completed on %date% at %time%

您甚至可以将这些信息存储在数据库的表中,这样这些信息就与数据库备份镜像保存在一起。定期地维护这些系统信息的历史记录可以为以后进行容量规划提供极有价值的帮助。

DB2 安全性审计

现在让我们看一个 DB2 系统命令的较好示例,该命令在用脚本语言进行自动化时非常有用。DB2 审计工具是一个实用程序,可以利用它充分地增强 DB2 实例和数据库安全性审计。它由名为 db2audit.exe 的 DB2 系统命令完全管理和控制。该命令使您能够全面地实现非常严格的 DB2 UDB 安全性审计实践。您可以配置、启动和停止安全性审计,并可以从该工具清除和抽取审计数据。这个过程是非常耗时的日常工作,但很容易用脚本语言使其自动化。例如,在您配置并启动 DB2 审计工具之后,您也许希望创建并调度一个脚本以定期地清除审计数据并将审计数据抽取到报告文件中。

清单 10. DB2 获取审计报告脚本(db2getaudit.bat)


@echo off
::---------------------------------------------------------------------------::
:: This is a Windows Shell Script to collect DB2 Audit Facility information.
:: You must first start the DB2 Audit Facility (db2audit start) and optionally
:: configure scope and status (db2audit configure scope all status both). It
:: flushes and extracts the audit data to the default DB2 Audit Facility
:: directory (sqllib<instance&g