| 免费下载:IBM® DB2® Express-C 9.7.2 免费版 或者 DB2® 9.7 for Linux®, UNIX®, and Windows® 试用版 |
|---|
| 下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。 |
在 DB2 数据库系统监控中,经常会遇到 CPU 资源使用过高问题,造成此类问题的原因很多,但最主要的原因有两个,第一是过多的逻辑 I/O 读取,第二就是过多的排序 (Sort),这两个因素有时也称为 CPU 的两大杀手。所谓过多的逻辑 I/O 读取,通常指发生在缓冲池中的表扫描。
排序是指对某些数据按照某个 ( 或某些 ) 字段从大到小或从小到大排列的过程。比如,按照学生成绩从高到低排序,根据姓氏字母顺序排序等。
在 DB2 数据库中,哪些操作会引起表数据排序呢?熟悉 SQL 的朋友立即会想到 Order By。没错,如果排序字段上没有索引,或者 DB2 认为索引的开销比表扫描更大时,DB2 就会对数据进行排序。
除 Order By 之外,在以下操作中也可能引起排序:
- 对于包含 DISTINCT,,GROUP BY, HAVING,INTERSECT,EXCEPT,UNION 等操作的 SQL 语句,如果没有索引满足所取的行的顺序要求,或者优化器认为排序的代价低于索引扫描,就需要进行排序;
- 对于包含 Max/Min/Sum/Cube/Rollup/Rank 等聚集函数,DB2 会把语句重写为一个使用排序的嵌套子查询;
- 对于 Reorg, Create Index 等操作,需要对表数据进行排序才能完成;
- 对于查询计划中的 Dynamic Bitmap Index ANDing(IXAND),Hash Join(HSJOIN)等操作的生成的 Hash 表会放在 SORTHEAP 中。
通常情况下,大量的排序会对性能造成极大影响。比如,排序会导致很高的 CPU 使用时间;增加 SQL 执行时间;增加锁超时和死锁发生的机率;排序会严重消耗有限的内存空间;排序溢出会引起临时表空间的频繁 I/O 等。在实际运维过程中,经常发现很多人对排序的监控和调优缺乏理论和实践经验,遇到相关问题时不知所措。本节首先介绍排序的原理,然后通过一个实例介绍排序的监控和诊断方法,最后提出减少排序的建议,希望对大家有所帮助。
正常情况下,DB2 排序发生在内存中,这块内存叫做排序堆,即 SORTHEAP。当需要排序的数据超出 SORTHEAP 大小限制时,就会发生排序溢出。溢出的数据会写到临时表中,这会产生更多的 I/O,因此对性能会有较大影响。
通过图 2-1 可知,DB2 的内存集包括实例内存集、数据库共享内存集、应用程序内存集和代理私有内存集等。内存池是从内存集中分配的。根据排序内存池的分配来源,分为私有排序和共享排序。私有排序是从代理私有内存集中分配的,而共享排序从数据库共享内存集中分配。
图 1.排序内存
SORTHEAP: 数据库配置参数,指定为每个排序分配的最大内存大小,实际使用的大小是由优化器来决定的。如果表的统计信息不准确,会导致优化器对要使用的排序内存的大小估算不准,有可能分配比实际需要少的内存,导致不必要的排序溢出。这就提醒我们要经常使用 runstat 来更新有频繁数据更改的表的统计信息。
SHEAPTHRES_SHR: 数据库配置参数,该参数指定了数据库共享内存集中共享排序内存池的大小,它限制了该数据库上的所有应用能达到的共享排序内存上限。在 DB2 8 版本中,这个值是硬限制,当达到此限制后,请求排序的新应用会收到 SQL0955(reason code 2) 错误。从 DB2 9.1 起,这个参数改为软限制,超过 SHEAPTHRES_SHR 的共享排序请求可以从数据共享内存集的溢出区 (Database overflow Buffer) 获得。
SHEAPTHRES: 实例配置参数 , 指定为本实例中所有私有排序分配的内存上限的软限制。当私有排序分配的内存达到了此限制,新请求的私有排序的内存大小分配将会小于 sortheap 配置的大小。
简单地说,每次排序是从 SORTHEAP 中分配的。如果使用私有排序,那么允许分配的排序内存大小不能超过 SHEAPTHRES 实例参数;如果使用共享排序,允许分配的排序内存大小不能超过 SHEAPTHRES_SHR 数据库参数。
那么如何配置 DB2 使用共享排序还是私有排序呢?从 DB2 9 开始,如果将 SHEAPTHRES 实例参数设置为 0,DB2 将使用共享排序,即排序内存从共享排序内存池中分配,排序内存的最大限制由 SHEAPTHRES_SHR 决定。
DB2 排序可以通过 SNAPSHOT 快照监控,快照监控结果提供了很多关于排序的信息,如总的排序次数、排序时间、排序溢出数量等。以下是数据库快照排序监控指标:
清单 1. 数据库快照排序监控指标
inst20@db2server:/data1/sh> db2 get snapshot for database on perfdb | more
Database Snapshot
Total Private Sort heap allocated = 9553
Total Shared Sort heap allocated = 0
Shared Sort heap high water mark = 0
Total sorts = 12936047
Total sort time (ms) = 19098348
Sort overflows = 83950
Active sorts = 1
… …
Commit statements attempted = 1130957
Rollback statements attempted = 519
|
Total sorts:表示发生的总排序次数; Total sort time(ms):表示发生的总排序时间; Sort overflows:表示发生的排序溢出次数; Active sorts:表示监控时正在进行的排序次数。
前三个指标是自数据库启动以来的统计值,最后一个指标是当前值。几个关键的指标如下:
- Sort overflows/Total sorts * 100% 表示排序溢出百分比,通常情况下,该值应该小于 3。如果大于 3,表示溢出的比例太高,需要优化;
- Total sorts time(ms)/Total sorts 表示每次排序花费的时间 ( 毫秒 ),对于交易系统来说,该值最好小于 50ms;
- Total sorts time(ms)/(Commit statements attempted + Rollback statements attempted) 表示每个事务花费在排序上的时间。一个事务响应时间包含很多方面,比如读 / 写时间、锁时间、排序时间、CPU 时间等。排序时间越少,最终用户的响应时间也越快,占用的 CPU 资源也越少。
上例中,在 4 天的时间内共计发生了 12936047 次排序,排序溢出比为 83950/12936047=0.6%,每个事务需要花费的排序时间为:19098348/(1130957+519) = 16ms。
除了数据库快照,应用程序快照、动态 SQL 快照也包含一些排序信息。这对于我们定位排序根源有很大帮助。以下是动态 SQL 语句快照片段,该语句平均每次执行需要 4 次排序,而且 3 次发生溢出,根据这些信息,该语句很明显需要优化。
清单 2. 动态 SQL 语句快照片段
Number of executions = 36 Number of compilations = 1 Worst preparation time (ms) = 18 Best preparation time (ms) = 15 Internal rows deleted = 0 Internal rows inserted = 0 Rows read = 57462636 Internal rows updated = 0 Rows written = 30062371 Statement sorts = 144 Statement sort overflows = 108 Total sort time = 145700 Buffer pool data logical reads = 19546362 Buffer pool data physical reads = 8 Buffer pool temporary data logical reads = 4141609 Buffer pool temporary data physical reads = 250 Buffer pool index logical reads = 35513607 Buffer pool index physical reads = 1096 Buffer pool temporary index logical reads = 0 Buffer pool temporary index physical reads = 0 Total execution time (sec.ms) = 355.390643 Total user cpu time (sec.ms) = 164.663270 Total system cpu time (sec.ms) = 1.529099 Statement text = select * from … ( 略 ) |
以上我们介绍了排序的监控,当发现排序的监控指标超出期望值时,就需要优化。影响排序的因素主要包括排序的行数、排序列的宽度和 ORDER BY 的列数等,排序的行数乘以排序列的宽度决定了一次排序占用的空间,因此,应该尽量减少排序的行数 ( 很多情况下,排序列无法更改 )。以下介绍一些常用的排序优化方法。
从 DB29 开始,SHEAPTHRES_SHR 实例参数的缺省值为 0,这表示排序内存从数据库共享内存区分配,排序总量由 SHEAPTHRES 数据库参数控制。 那么,如何设置 SORTHEAP 和 SHEAPTHRES 的大小呢?
首先 SORTHEAP 是每次排序能够分配的最大内存空间,当排序的数值超过该值时,就要发生排序溢出,SORTHEAP 的缺省大小是 256 页,即 1M。假定,要排序的数据每行是 1K 大小,那么每个 SORTHEAP 最多允许排序 1M/1K=1000 行,超出 1000 行数据,排序将会溢出。
inst20@db2server:/data1/sh> db2 get db cfg for sample | grep -i sort Sort heap thres for shared sorts (4KB) (SHEAPTHRES_SHR) = 5000 Sort list heap (4KB) (SORTHEAP) = 256 |
对于数据仓库系统来说,一般行记录很长,排序的行数也很多,这是可考虑适当增大 SORTHEAP 大小,但不要扩的太大。
SHEAPTHRES_SHR 参数,用来限定所有排序可以占用的内存空间。该值的大小由两个指标来决定,一个是 SORTHEAP,另外一个是同时排序的个数。但是,同时排序的个数很难估计,一般采用并发数来估计。以下的监控结果可知,当时正在并发的应用数量大概是 10 个。
db2inst1@ibmswg01:~/> db2 get snapshot for database on prefdb Appls. executing in db manager currently = 10 |
考虑到单个应用可能需要进行多次排序,可设置: SHEAPTHRES_SHR = SORTHEAP * 应用并发数 * 2 在 9.1 及以上版本,DB2 提供了自动调优功能 (STMM),好处是 DB2 根据工作负载和资源情况,决定一些内存的分配和回收,比如:缓冲池、排序堆、锁列表和 Package cache 大小,当需要排序时,可以从别的内存区借用,当不需要时归回,充分利用内存使用。对于运行稳定的系统,可考虑启用 STMM,设置这两个参数为 automatic 自动值。
inst20@db2server:/data1/sh> db2 update db cfg for perfdb using SORTHEAP automatic inst20@db2server:/data1/sh> db2 update db cfg for perfdb using SHEAPTHRES_SHR automatic |
调整参数有些情况下能解决问题,但可能会隐藏问题,因为调参只是尽量减少排序溢出的几率,并不能减少排序的次数。因此,作为一个优秀的 DBA,需要挖掘排序的根源,并给出解决方案。根源是什么?尽管 Reorg、建索引等操作需要排序,但几乎 99% 的概率是 SQL 语句引起的。在 SQL 语句无法更改的情况下,作为 DBA,能够做的就是在物理设计上做优化。 那么如何找到哪些语句发生了大量排序呢?答案就是我们前面介绍过的动态 SQL 快照和应用快照监控。 当找到 SQL 语句后,就可以通过一些物理设计来优化 SQL,如索引、物化视图 (MQT) 等。当然,一些影响优化器的运维工作也必不可少,如 runstats,reorg,rebind 等操作。 索引是减少排序的利器,因为索引本身已经是经过排序的数状结构。创建合适的索引会大大减少、甚至避免排序。当 SQL 语句中出现以下操作时,可以考虑在相应的字段上创建索引:
- Order By/Group By 操作,如: SELECT a,b,c FROM tab1 ORDER BY a,b SELECT a,b,c FROM tab1 WHERE a=100 ORDER BY b SELECT a,b,count(*),sum(*) FROM tab1 group by a,b 这时可考虑在 tab1(a,b) 上建索引。
- Distinct 操作,如:SELECT distinct a FROM tab1 可考虑在 tab(a) 上建索引,对于 distinct 的查询可避免排序。
- Hash Join 操作需要在 SORTHEAP 中建立哈希表,对于发生大量 Hash Join 的表,可考虑建立索引。
- Create index idx_1 on tab1(a) allow reverse scan 建索引时考虑用 Allow Reverse Scans 进行索引值逆向扫描,这也是 DB2 9 的缺省选项。
如果通过 3.1 和 3.2 的步骤仍然不能解决排序问题,那就需要对 SQL 语句本身进行逻辑调整和修改。比如:
- 能否在 SQL 语句中省略 ORDER BY, DISTINCT 等操作,如果无法省略,能否尽量减少排序的行数或列数,比如通过增加过滤条件等;
- 如果 UNION All 能满足需求,就避免用 UNION,因为 UNION All 不需要排序;
- 写优化的 SQL 语句,比如不要在排序字段上使用函数。
下面我们通过一个详细的例子说明对排序问题的诊断分析过程。
搭建实验环境
以下实验在 DB2 Version 9.5 for Linux 下运行。首先创建一个 SORTDB 数据库,然后创建一个 EMPLOYEE 员工表,并插入 100 万行数据,其中 DEPT_ID 字段是随机产生的 1000 个部门编号,所有员工数据均匀分布在 1000 个部门里,每个部门大概包含 100 万 /1000=1000 个员工。 脚本如下 ( 以下命令存到一个脚本文件中 create.ddl):
-- 创建测试 database
create db sortdb@
-- 更改日志参数,否则会在插入数据时出现 log full
update db cfg for sortdb using logfilsiz 2000 @
update db cfg for sortdb using logprimary 20@
update db cfg for sortdb using logsecond 30@
-- 日志参数的更改需要断掉连接才会生效
force applications all@
-- 连接数据库
connect to sortdb@
-- 创建 bufferpool
create bufferpool bp4k size 10000@
-- 创建 automatic storaged tablespace
create tablespace emp_dms bufferpool bp4k@
-- 创建 table
create table db2inst1.employee
( emp_id int not null primary key,
name char(20),
dept_id int,
salary decimal,
address char(30),
remark char(40)
) in emp_dms
@
-- 向表里插入 100 万条数据,其中 dept_id 的范围为 0-1000,其余几个 char 字段值都是根据 count 值产生
begin atomic
declare count int default 1;
while (count <1000000) do
insert into db2inst1.employee values(
count,
'--emp' concat char(count),
ceiling( (rand()*1000) ),
20000.50,
'-----address' concat char(count) concat '---',
'------remark' concat char(count) concat '----'
);
set count=count+1;
end while;
end
@
-- 对表做 runstats
runstats on table db2inst1.employee @
|
执行 db2 -td@ -f create.ddl 命令创建脚本。
然后设置排序参数,sortheap=250,sheapthresshr=1000,并打开监控开关。
inst20@db2server:/backup> db2 update db cfg for sortdb using sheapthres_shr 10000 sortheap 250 DB20000I The UPDATE DATABASE CONFIGURATION command completed successfully. inst20@db2server:/backup> db2 update dbm cfg using SHEAPTHRES 0 DB20000I The UPDATE DATABASE MANAGER CONFIGURATION command completed successfully. inst20@db2server:/backup> db2 UPDATE DBM CFG USING DFT_MON_SORT ON DB20000I The UPDATE DATABASE MANAGER CONFIGURATION command completed successfully. inst20@db2server:/backup> db2stop force 06/03/2011 07:33:04 0 0 SQL1064N DB2STOP processing was successful. inst20@db2server:/backup> db2start 06/03/2011 07:33:15 0 0 SQL1063N DB2START processing was successful. |
然后查询 dept_id < 100 的记录,并按 dept_id 排序,大概会有 9 万 9 千行记录返回。
inst20@db2server:/backup> db2 "SELECT dept_id, name FROM db2inst1.employee WHERE dept_id <100 ORDER BY dept_id" | grep selected 99011 record(s) selected. |
对排序问题的诊断和分析
现在我们要通过数据库监控,查找排序问题的根源。
1.数据库监控分析
通过监控结果可知,在共享内存区发生了一次排序,并且发生了排序溢出,排序时间是 204ms。以下监控是 SQL 语句完成后执行的,所以 Total Shared Sort heap allocated 的结果是 0,否则会显示当前分配的排序堆页数。因为是共享排序,所有与私有排序相关的参数都是 0。
inst20@db2server:/backup> db2 get snapshot for db on sortdb | more Total Private Sort heap allocated = 0 Total Shared Sort heap allocated = 0 Shared Sort heap high water mark = 250 Post threshold sorts (shared memory) = 0 Total sorts = 1 Total sort time (ms) = 206 Sort overflows = 1 Active sorts = 0 |
然后监控缓冲池临时数据和临时索引的逻辑读 / 写页数,当排序溢出时,会溢出到临时表空间中。如果发现临时数据读写值较高,那么很可能是 SORT 引起的。
inst20@db2server:/backup> db2 get snapshot for database on sortdb|grep -i "temporary data" Buffer pool temporary data logical reads = 1792 Buffer pool temporary data physical reads = 31 Buffer pool temporary index logical reads = 0 Buffer pool temporary index physical reads = 0 |
2.监控 SQL 语句
接着根据动态 SQL 语句快照,找到排序多、溢出多的 SQL 语句。我们会发现,该语句执行了一次,执行时间花费了 7.6 秒,Rows Read=1099018, Rows Written= 99011。排序发生了一次,溢出一次。可能有人有会比较奇怪,为什么 select 语句会产生 rows written 呢?这就是因为排序溢出写到临时表空间,产生了写 I/O,溢出的行数为 99011,正对应前面的查询结果。
Number of executions = 1 Number of compilations = 1 Worst preparation time (ms) = 134 Best preparation time (ms) = 134 Internal rows deleted = 0 Internal rows inserted = 0 Rows read = 1099018 Internal rows updated = 0 Rows written = 99011 Statement sorts = 1 Statement sort overflows = 1 Total sort time = 204 Buffer pool data logical reads = 30561 Buffer pool data physical reads = 2367 Buffer pool temporary data logical reads = 1792 Buffer pool temporary data physical reads = 1 Buffer pool index logical reads = 35 Buffer pool index physical reads = 27 Buffer pool temporary index logical reads = 0 Buffer pool temporary index physical reads = 0 Buffer pool xda logical reads = 0 Buffer pool xda physical reads = 0 Buffer pool temporary xda logical reads = 0 Buffer pool temporary xda physical reads = 0 Total execution time (sec.microsec)= 7.612814 Total user cpu time (sec.microsec) = 0.938412 Total system cpu time (sec.microsec)= 0.000000 Total statistic fabrication time (milliseconds) = 0 Total synchronous runstats time (milliseconds) = 0 Statement text = SELECT dept_id, name FROM db2inst1.employee WHERE dept_id < 100 ORDER BY dept_id |
当然,也可以使用 SYSIBMADM.SNAPDYN_SQL 管理视图找到排序最多的动态 SQL 语句。
3.SQL 语句分析
通过 explain 工具生成 SQL 语句的执行计划,并通过 db2exfmt 进行格式化。
inst20@db2server:~/sqllib/misc> db2 -tvf EXPLAIN.DDL inst20@db2server:~> more query.sql SELECT dept_id, name FROM db2inst1.employee WHERE dept_id < 100 ORDER BY dept_id; inst20@db2server:~> db2 set current explain mode explain DB20000I The SQL command completed successfully. inst20@db2server:~> db2 -tvf query.sql SELECT dept_id, name FROM db2inst1.employee WHERE dept_id < 100 ORDER BY dept_id SQL0217W The statement was not executed as only Explain information requests are being processed. SQLSTATE=01604 inst20@db2server:~> db2exfmt -1 -d sortdb -o query_exfmt.out |
然后打开 query_exfmt.out 文件,计划如下:
Access Plan:
-----------
Total Cost: 36010
Query Degree: 1
Rows
RETURN
( 1)
Cost
I/O
|
98999.9
TBSCAN
( 2)
36010
30763
|
98999.9
SORT
( 3)
35270.1
30094.5
|
98999.9
TBSCAN
( 4)
30134.7
29426
|
999999
TABLE: DB2INST1
EMPLOYEE
Q1
|
通过以上结果可知,在对表 EMPLOYEE 进行 TBSCAN 后,有一次 SORT 操作,然后对 SORT 的结果再次 TBSCAN。观察 TBSCAN(4),SORT(3) 和 TBSCAN(2)这三个操作符的累计 I/O 次数,可以看出 I/O 在增长,这是个典型的 SORT 溢出。 那么再看 SORT 操作符的具体信息:
3) SORT : (Sort) Cumulative Total Cost: 35270.1 Cumulative CPU Cost: 2.59546e+09 Cumulative I/O Cost: 30094.5 Cumulative Re-Total Cost: 0 Cumulative Re-CPU Cost: 0 Cumulative Re-I/O Cost: 668.5 Cumulative First Row Cost: 35270.1 Estimated Bufferpool Buffers: 30318 Arguments: --------- DUPLWARN: (Duplicates Warning flag) FALSE NUMROWS : (Estimated number of rows) 99000 ROWWIDTH: (Estimated width of rows) 32 SORTKEY : (Sort Key column) 1: Q1.DEPT_ID(A) SPILLED : (Pages spilled to bufferpool or disk) 892 TEMPSIZE: (Temporary Table Page Size) 4096 UNIQUE : (Uniqueness required flag) FALSE Input Streams: ------------- 2) From Operator #4 Estimated number of rows: 98999.9 Number of columns: 2 Subquery predicate ID: Not Applicable Column Names: ------------ +Q1.NAME+Q1.DEPT_ID Output Streams: -------------- 3) To Operator #2 Estimated number of rows: 98999.9 Number of columns: 2 Subquery predicate ID: Not Applicable Column Names: ------------ +Q1.DEPT_ID(A)+Q1.NAME |
通过以上排序操作可知,有 892 页发生了排序溢出。DB2 优化器预测的排序行数是 99000 行,每行宽度是 32 个字节,所以需要的排序空间至少是 99000*32/1024=3093k=3.1M 左右,而 SORTHEAP 设定的排序内存是 250*4K=1M,所以发生了排序溢出。
排序溢出处理
发生排序溢出时,第一个要考虑的就是调整 SORTHEAP 参数,本例中我们将 SORTHEAP 参数值由 250 页 (1M) 增加到 2500 页 (10M)。为便于对比,我们把以前的监控结果清零。
inst20@db2server:~> db2 update db cfg for sortdb using sortheap 2500 DB20000I The UPDATE DATABASE CONFIGURATION command completed successfully. inst20@db2server:~> inst20@db2server:~> inst20@db2server:~> db2 reset monitor all DB20000I The RESET MONITOR command completed successfully. |
然后再次执行 SQL 语句,并观察结果。没有发现排序溢出,并且排序时间是 162ms,小于之前的 206ms。
[db2inst1@ibmswg01]$ db2 get snapshot for db on sortdb | more Total Private Sort heap allocated = 0 Total Shared Sort heap allocated = 0 Shared Sort heap high water mark = 2322 Post threshold sorts (shared memory) = 0 Total sorts = 1 Total sort time (ms) = 162 Sort overflows = 0 Active sorts = 0 |
再次查看 SQL 语句的执行计划,
Access Plan:
-----------
Total Cost: 30201.9
Query Degree: 1
Rows
RETURN
( 1)
Cost
I/O
|
98999.9
TBSCAN
( 2)
30201.9
29426
|
98999.9
SORT
( 3)
30201.9
29426
|
98999.9
TBSCAN
( 4)
30134.7
29426
|
999999
TABLE: DB2INST1
EMPLOYEE
Q1
3) SORT : (Sort)
Cumulative Total Cost: 30201.9
Cumulative CPU Cost: 2.55223e+09
Cumulative I/O Cost: 29426
Cumulative Re-Total Cost: 30134.6
Cumulative Re-CPU Cost: 2.34872e+09
Cumulative Re-I/O Cost: 0
Cumulative First Row Cost: 30201.9
Estimated Bufferpool Buffers: 29426
Arguments:
---------
DUPLWARN: (Duplicates Warning flag)
FALSE
NUMROWS : (Estimated number of rows)
99000
ROWWIDTH: (Estimated width of rows)
32
SORTKEY : (Sort Key column)
1: Q1.DEPT_ID(A)
TEMPSIZE: (Temporary Table Page Size)
4096
UNIQUE : (Uniqueness required flag)
FALSE
Input Streams:
-------------
2) From Operator #4
Estimated number of rows: 98999.9
Number of columns: 2
Subquery predicate ID: Not Applicable
Column Names:
------------
+Q1.NAME+Q1.DEPT_ID
Output Streams:
--------------
3) To Operator #2
Estimated number of rows: 98999.9
Number of columns: 2
Subquery predicate ID: Not Applicable
Column Names:
------------
+Q1.DEPT_ID(A)+Q1.NAME
|
对比前面的访问计划,可以看到 TBSCAN(4),SORT(3) 和 TBSCAN(2)这三个操作符的累计 I/O 次数一直保持不变,SORT(3)操作中没有溢出。整个语句的 Cost 由 36010 降为 30201.9。
查看 SQL 语句执行时间,由 7.6 秒将为 6.97 秒。
消除排序
尽管调整参数后,排序溢出消失,但速度仍然较慢。接下来要做的是如何消除排序,采用的方法是创建索引。 DB2 提供了一个很有效的索引推荐工具,db2advis。
db2advis -d sortdb -i advisesql.txt -n db2inst1 -o newindex.ddl |
从 newindex.ddl 可以看到,推荐了如下索引:
-- LIST OF RECOMMENDED INDEXES
-- ===========================
-- index[1], 41.149MB
CREATE INDEX "DB2INST1"."IDX_EMP_DEPTID" ON "DB2INST1"."EMPLOYEE"
("DEPT_ID" ASC, "NAME" DESC) ALLOW REVERSE SCANS ;
COMMIT WORK ;
RUNSTATS ON TABLE "DB2INST1"."EMPLOYEE" FOR INDEX "DB2INST1"." IDX_EMP_DEPTID " ;
COMMIT WORK ;
|
创建索引:
db2 – tvf newindex.ddl |
再次执行 SQL 语句,观察生成的执行计划,这是一个非常的高效的索引只读计划,没有任何排序。整个语句的 Cost 也大幅降为 1147.64,SQL 语句的执行时间变为 3.9 秒。
Access Plan:
-----------
Total Cost: 1164.35
Query Degree: 1
Rows
RETURN
( 1)
Cost
I/O
|
98999.9
IXSCAN
( 2)
1164.35
1043.44
|
999999
INDEX: DB2INST1
IDX_EMP_DEPTID
Q1
|
本文讲解了 DB2 排序的概念,排序相关的配置和监控方法,并通过一个实例详细演示了排序问题的监控和调优,希望对大家有所帮助。
学习
- 通过
developerWorks Information Management 专区 学习关于 IM 的更多知识。
- 通过 IM 专区
DB2 9 技术资源中心 了解 DB2 产品更多信息和相关技术。
- 通过 DB2 V9.7 信息中心的
DB2 9 产品信息中心 了解关于 DB2 数据库的更多内容。
-
随时关注 developerWorks技术活动和 网络广播。
获得产品和技术
- 要开始学习,请先下载并安装
DB2 Express-C或者 DB2 Enterprise Edition 试用版本。
讨论
- 如有任何疑问,可以访问
DB2 Express-C 论坛或 DB2 中国网站。
- 加入
developerWorks
博客,并加入 My developerWorks 中文社区;您可以通过个人档案和定制主页获得符合自己的兴趣的 developerWorks 文章,并与其他 developerWorks 用户进行交流。