查看: 4263|回复: 6

[精华] 例程: 多分区针对某一SQL优化

[复制链接]
招聘 : c/c++研发
论坛徽章:
45
技术图书徽章
日期:2014-03-10 14:09:192012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-01-04 11:51:22ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:50
跳转到指定楼层
1#
发表于 2007-7-26 21:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
问题描述:
客户有两系统,两套系统中数据完全一样,一套系统为8分区,另一系统为16分区.
现在客户有一update语句:
UPDATE mf.POSITION t
   SET start_dt = (SELECT d2.DATE_ID
                     FROM mf.DATE d1,
                          mf.DATE d2
                    WHERE d1.date_id = t.start_dt
                      AND d2.CALENDAR_DATE = d1.PRIOR_BUS_DAY_DATE)
    where t.start_dt > 19010101
;

这条语句在8分区系统中运行时间24分钟,在16分区系统中运行超过24小时....

环境:
16分区环境:

Server is running MPP/EEE.
DB21085I  Instance "db2apdw" uses "64" bits and DB2 code release "SQL09011"
with level identifier "01020107".
Informational tokens are "DB2 v9.1.0.1", "s061104", "U809676", and Fix Pack
"1".
Product is installed at "/opt/IBM/db2/V9.1_01".

8分区环境为v9 GA

两边的DDL完全相同:

------------------------------------------------
-- DDL Statements for table "MF    "."DATE"
------------------------------------------------


CREATE TABLE "MF     "."DATE"  (
                  "DATE_ID" INTEGER NOT NULL ,
                  "CALENDAR_DATE" DATE ,
                  "DAY_OF_WEEK" SMALLINT ,
                  "DAY_NUM_IN_MONTH" SMALLINT ,
                  "DAY_NAME" VARCHAR(9) ,
                  "DAY_ABBREV" CHAR(3) ,
                  "WEEKDAY_FLAG" CHAR(1) ,
                  "WEEK_NUM_IN_YEAR" SMALLINT ,
                  "WEEK_BEGIN_DATE" DATE ,
                  "WEEK_ENDING_DATE" DATE ,
                  "MONTH_NUM" SMALLINT ,
                  "MONTH_NAME" VARCHAR(9) ,
                  "MONTH_ABBREV" CHAR(3) ,
                  "MONTH_END_DATE" DATE ,
                  "QUARTER_NUM" SMALLINT ,
                  "QUARTER_NAME" CHAR(2) ,
                  "YEAR_QUARTER_NAME" CHAR(7) ,
                  "YEAR_NUM" SMALLINT ,
                  "YEAR_MONTH_NUM" INTEGER ,
                  "YEAR_QUARTER_NUM" INTEGER ,
                  "FISCAL_WEEK" SMALLINT ,
                  "FISCAL_MONTH" SMALLINT ,
                  "FISCAL_QUARTER" SMALLINT ,
                  "FISCAL_YEAR" SMALLINT ,
                  "LAST_DAY_IN_MONTH_FLAG" CHAR(1) ,
                  "CURR_DAY_FLAG" CHAR(1) ,
                  "CURR_WEEK_FLAG" CHAR(1) ,
                  "CURR_MONTH_FLAG" CHAR(1) ,
                  "US_BANK_HOLIDAY_FLAG" CHAR(1) ,
                  "US_EXCH_HOLIDAY_FLAG" CHAR(1) ,
                  "BW_PRELIM_FLAG" CHAR(1) ,
                  "BW_MONTHEND_FLAG" CHAR(1) ,
                  "LAST_BUS_DAY_IN_MONTH_FLAG" CHAR(1) ,
                  "ETL_PROCESS_ID" INTEGER NOT NULL WITH DEFAULT 0 ,
                  "ETL_USER_ID" INTEGER NOT NULL WITH DEFAULT 0 ,
                  "ETL_CREATE_TS" TIMESTAMP NOT NULL WITH DEFAULT CURRENT TIMESTAMP ,
                  "ETL_UPDATE_TS" TIMESTAMP ,
                  "QUARTER_END_DATE" DATE ,
                  "YEAR_END_DATE" DATE ,
                  "PRIOR_BUS_DAY_DATE" DATE ,
                  "PRIOR_MONTH_END_DATE" DATE ,
                  "PRIOR_QUARTER_END_DATE" DATE ,
                  "PRIOR_YEAR_END_DATE" DATE ,
                  "TRAILING_TWELVE_MONTH_END_DATE" DATE )   
                 DISTRIBUTE BY HASH("DATE_ID"   
                   IN "ACR_DATE" INDEX IN "ACR_IDXS" ;

...
------------------------------------------------
-- DDL Statements for table "MF      "."POSITION"
------------------------------------------------


CREATE TABLE "MF      "."POSITION"  (
                  "AS_OF_DT" INTEGER ,
                  "START_DT" INTEGER NOT NULL ,
                  "END_DT" INTEGER NOT NULL ,
                  "LMR_SOURCE_ID" INTEGER NOT NULL ,
                  "LMR_INSTR_ID" INTEGER NOT NULL ,
                  "LMR_ACCT_ID" INTEGER NOT NULL ,
                  "CD_POSITION_TYPE_ID" INTEGER ,
                  "LMR_POSITION_TYPE_ID" INTEGER ,
                  "CD_PERF_SECTOR_ID" INTEGER ,
                  "QTY" DECIMAL(19,4) ,
                  "ORIG_FACE" DECIMAL(17,2) ,
                  "BASE_MKT_VALUE" DECIMAL(17,2) ,
                  "BASE_AVG_COST" DECIMAL(17,2) ,
                  "BASE_AVG_PRICE" DECIMAL(17,2) ,
                  "BASE_ACCRUED_INCOME" DECIMAL(17,2) ,
                  "BASE_UNREALIZED_GL" DECIMAL(17,2) ,
                  "BASE_AMORTIZED_COST" DECIMAL(17,4) ,
                  "YTM" DECIMAL(17,4) ,
                  "BASE_COMMISSION" DECIMAL(17,2) ,
                  "LOCAL_MKT_VALUE" DECIMAL(17,2) ,
                  "LOCAL_AVG_COST" DECIMAL(17,2) ,
                  "LOCAL_AVG_PRICE" DECIMAL(17,2) ,
                  "LOCAL_ACCRUED_INCOME" DECIMAL(17,2) ,
                  "LOCAL_UNREALIZED_GL" DECIMAL(17,2) ,
                  "LOCAL_COMMISSION" DECIMAL(17,2) ,
                  "FX_RATE" DECIMAL(20,5) ,
                  "LMR_BASE_CURRENCY_ID" INTEGER ,
                  "LMR_LOCAL_CURRENCY_ID" INTEGER ,
                  "ETL_PROCESS_ID" INTEGER NOT NULL WITH DEFAULT 0 ,
                  "ETL_USER_ID" INTEGER NOT NULL WITH DEFAULT 0 ,
                  "ETL_CREATE_TS" TIMESTAMP NOT NULL WITH DEFAULT CURRENT TIMESTAMP ,
                  "ETL_UPDATE_TS" TIMESTAMP )   
                 DISTRIBUTE BY HASH("LMR_ACCT_ID"   
                   IN "ACR_POSITION" INDEX IN "ACR_IDXS" ;

两个table所在tablespace都是跨所有分区,具体的DDL就不贴了

在16分区系统中使用的access plan:

  1. Access Plan:
  2. -----------
  3.         Total Cost:             3.97053e+07
  4.         Query Degree:           1

  5.                    Rows
  6.                   RETURN
  7.                   (   1)
  8.                    Cost
  9.                     I/O
  10.                     |
  11.                   465308
  12.                   UPDATE
  13.                   (   2)
  14.                 3.97053e+07
  15.                   472862
  16.                 /----+---\
  17.            465308        465308
  18.            NLJOIN    TABLE: MF
  19.            (   3)       POSITION
  20.          3.6185e+07
  21.             7554
  22.           /---+---\
  23.      465308          1
  24.      TBSCAN       BTQ
  25.      (   4)       (   5)
  26.      7808.78      117.907
  27.       7507        33.0625
  28.        |            |
  29.      465308       0.0625
  30. TABLE: MF        MSJOIN
  31.     POSITION      (   6)
  32.                   117.734
  33.                   33.0625
  34.               /------+------\
  35.           39664           1.57574e-06
  36.          TBSCAN             FILTER
  37.          (   7)             (  13)
  38.          102.187            8.04381
  39.            32               1.0625
  40.            |                  |
  41.           39664             0.0625
  42.          TEMP               TBSCAN
  43.          (   8)             (  14)
  44.          66.4508            8.04381
  45.            32               1.0625
  46.            |                  |
  47.           39664             0.0625
  48.          MBTQ               SORT
  49.          (   9)             (  15)
  50.          52.0979            8.04317
  51.            32               1.0625
  52.            |                  |
  53.           2479              0.0625
  54.          TBSCAN             FETCH
  55.          (  10)             (  16)
  56.          35.7837            8.04202
  57.            32               1.0625
  58.            |               /---+---\
  59.           2479        0.0625        2479
  60.          SORT         IXSCAN   TABLE: MF
  61.          (  11)       (  17)        DATE
  62.          34.6639      7.56908
  63.            32            1
  64.            |            |
  65.           2479         2479
  66.          TBSCAN   INDEX: MF
  67.          (  12)      DATE_IDX1
  68.          32.6103
  69.            32
  70.            |
  71.           2479
  72.      TABLE: MF
  73.           DATE
复制代码


在8分区系统中:

  1.         Total Cost:             9.66272e+06
  2.         Query Degree:           1

  3.                    Rows
  4.                   RETURN
  5.                   (   1)
  6.                    Cost
  7.                     I/O
  8.                     |
  9.                 1.05788e+06
  10.                   UPDATE
  11.                   (   2)
  12.                 9.66272e+06
  13.                 1.07495e+06
  14.                 /----+----\
  15.          1.05788e+06    1.05788e+06
  16.            NLJOIN     TABLE: MF
  17.            (   3)        POSITION
  18.          1.6609e+06
  19.             17069
  20.           /---+---\
  21.    1.05788e+06       1
  22.      TBSCAN       BTQ
  23.      (   4)       (   5)
  24.      17765.2      142.679
  25.       17066         17
  26.        |            |
  27.    1.05788e+06     0.125
  28. TABLE: MF        NLJOIN
  29.     POSITION      (   6)
  30.                   17.6203
  31.                    2.125
  32.                  /---+---\
  33.                1          0.125
  34.             BTQ          IXSCAN
  35.             (   7)       (  10)
  36.             10.0424      7.57788
  37.              1.125          1
  38.               |            |
  39.              0.125        5031
  40.             FETCH    INDEX: MF
  41.             (   8)      DATE_IDX2
  42.             8.52351
  43.              1.125
  44.            /---+---\
  45.        0.125        5031
  46.       IXSCAN   TABLE: MF
  47.       (   9)        DATE
  48.       7.57769
  49.          1
  50.         |
  51.        5031
  52.   INDEX: MF
  53.      DATE_IDX1

复制代码


问题分析:
首先当我们第一眼看到这个问题的时候,第一个映射到我们脑子里的想法是什么?

俺第一个想到的是access plan得问题.因为在8分区中的access plan喝16分区中的不同,而estimate cost同样也是在8分区中的比较小,因此,第一个所想到的肯定是访问计划出问题了.

那么我们就需要考虑,到底是什么引起的这个问题呢.

在16分区的计划中我们可以看到那个MSJOIN,其左边的子树包含table queue,
          39664   
         MBTQ  
         (   9)  
         52.0979      
        32     
可以看出每一个TQ的预期输出为39664行,对比8分区的NLJN下的TQ的输出结果预期为1行,而MSJOIN上面的TQ的cost甚至要小于NLJN上面TQ的cost,可以初步想象为network cost heuristic出现问题.

那么什么地方能够控制network cost呢?答案就是comm_speed.
在8分区中我们有:
        Parallelism:            Inter-Partition Parallelism
        CPU Speed:              3.070237e-07
        Comm Speed:             1
        Buffer Pool size:       66280
        Sort Heap size:         8192
        Database Heap size:     1500
        Lock List size:         50000
        Maximum Lock List:      10
        Average Applications:   1
        Locks Available:        320000

16分区中为
        Parallelism:            Inter-Partition Parallelism
        CPU Speed:              4.251098e-07
        Comm Speed:             100
        Buffer Pool size:       66280
        Sort Heap size:         8192
        Database Heap size:     10000
        Lock List size:         50000
        Maximum Lock List:      10
        Average Applications:   1
        Locks Available:        320000

这里可以看到,在16分区中,由于comm_speed设置过高,所以使得heuristic产生错误的结果.

将该值调整为1,我们在16分区中也得到同样的access plan.

但是,现在尽管access plan完全一样,可是依然是用超过6小时.这个是怎么回事呢?

让我们继续来看访问计划,我们可以看到在plan中有两个table queue,而且两个table queue都是broadcast to all partitions.回头去检查SQL,发现join方式为A join B and B join B,根据计划看来,对于A中的每一条记录(也就是NLJN左边的POSITION table),都会对右边的子树作检索.

在右边的子树中同样有NLJN,对B and B作join,发送每个分区的B中所有数据到其他分区.

可以想象,这种correlation会对网络造成极大的压力,而且该压力随分区的增多而成指数级增长,做以下db2trc -pcf可以看到tablequeue操作占用了大量的时间,而对每一条数据的平均等待时间为大约30秒 (幸好不是block操作,要不然估计一年也弄不完这几亿条数据) ,而一秒钟的tablequeue read高达2400多次...

于是乎,结论是不是已经出来了呢?把DATE表整合到一个单独的分区中,作同样的操作,嘿嘿,13分钟解决战斗!
论坛徽章:
9
授权会员
日期:2006-06-15 15:15:15会员2007贡献徽章
日期:2007-09-26 18:42:10ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44铁扇公主
日期:2007-10-26 16:08:48生肖徽章2007版:鼠
日期:2008-01-02 17:35:532008新春纪念徽章
日期:2008-02-13 12:43:03奥运会纪念徽章:田径
日期:2008-08-19 09:59:402010广州亚运会纪念徽章:高尔夫球
日期:2010-11-22 15:29:49优秀写手
日期:2014-02-28 06:00:13
2#
发表于 2007-7-26 22:47 | 只看该作者
腚啊,我腚啊,写得很好啊。

使用道具 举报

回复
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412010广州亚运会纪念徽章:橄榄球
日期:2011-05-22 10:54:33管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012010年世界杯参赛球队:丹麦
日期:2010-04-06 10:23:36
3#
发表于 2007-7-27 07:58 | 只看该作者
如果是dw的应用,date表又是cube的,一般都放在独立分区里面
另外,数据在各个分区的分布是均衡的吗?

使用道具 举报

回复
招聘 : c/c++研发
论坛徽章:
45
技术图书徽章
日期:2014-03-10 14:09:192012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-01-04 11:51:22ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:50
4#
 楼主| 发表于 2007-7-27 08:26 | 只看该作者
忘了说了,是均匀的,甚至join后的数据分布也是均匀的

使用道具 举报

回复
论坛徽章:
21
在线时间
日期:2007-07-25 04:01:022012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:23马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:09:23
5#
发表于 2007-7-27 08:52 | 只看该作者
create small table in a single partition then replicate to all the partitions?

Tablequeue

使用道具 举报

回复
论坛徽章:
0
6#
发表于 2007-7-29 11:28 | 只看该作者
写的好

使用道具 举报

回复
论坛徽章:
0
7#
发表于 2007-7-30 14:23 | 只看该作者
好贴!

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表