网站首页/技术开发列表/内容

运用DB2look 重新创建优化器访问计划(4)

技术开发2024-04-12阅读
生成 db2exfmt 输出: 

db2exfmt -d DUMMYDB -g TIC -w -1 -n % -s % -# 0 -o test_dummydb_exfmt.txt 

检查 test_dummydb_exfmt.txt 的内容并查看访问计划: 

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

              Rows  
             RETURN  
             (   1)  
              Cost  
               I/O  
               | 
                4  
             MSJOIN 
             (   2)  
             25.8843  
                2  
          /-----+-----\ 
        1                4  
     TBSCAN           TBSCAN  
     (   3)           (   5)  
     12.913           12.9682  
        1                1  
       |                | 
        8               35  
 TABLE: SKAPOOR   TABLE: SKAPOOR   
       ORG             STAFF  

您在测试中获得了一个不同于生产中的访问计划。本例中,显然我们在测试系统上已经将 DFT_QUERYOPT(默认的查询优化)从 5 修改为 3。因此,您看到的是 Merge Join 计划,而非 Hash Join 计划,以及有一点点区别的总成本(Total Cost)。 
因为这些计划不匹配(假设您不确定为什么),所以要检查 db2exfmt 输出中的配置。见 表 2。 
正如您可以看到的,测试(TEST)和生产(PRODUCTION)之间的惟一区别就是优化级别(Optimization Level),我们特意将之从 5 修改为 3,只是为了显示在测试环境中复制生产访问计划为何会不成功。 
本例中,您将使用下列 UPDATE 语句将 DFT_QUERYOPT 更新为 5: 

UPDATE DB CFG FOR SAMPLE USING dft_queryopt 5 

然后,停止并重新连接数据库。再次对 DUMMYDB 发出 query.sql,并使用 db2exfmt 命令生成访问计划。这次,您将看到相同的访问计划。否则,就进一步确保本文中所讨论的所有优化器相关的参数都是相同的。 
示例 2: 
该示例显示了 db2look 命令中 -m 选项的重要性。前面用 -m 选项收集的统计数据在测试和生产中应该相同。本例中,我们将看到没有正确更新统计数据时计划是如何变化的。  
数据库管理器配置、数据库配置和 db2set 注册表变量与上面 示例 1 中的相同。这里的模式名是 SKAPOOR。用您的表的模式替换它。数据库是相同的,与 示例 1 中一样是 SAMPLE 和 DUMMY。这里所使用的平台和 db2level 是 AIX 5.1 和 DB2 UDB ESE V8.2,Fix pack 8,单分区。 
在 sample 数据库上执行下列命令: 

db2 "connect to sample" 
db2 "create index name_ind on staff (name,id)" 
db2 "runstats on table skapoor.staff with distribution and indexes all" 
db2 "set current explain mode explain" 
db2 "select name from staff where id=10 order by name" 
db2 "set current explain mode no" 
db2 "terminate" 

使用 db2exfmt 生成访问计划。您将看到下面的访问计划:  

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

      Rows 
     RETURN 
     (   1) 
      Cost 
       I/O 
       | 
        1 
     IXSCAN 
     (   2) 
    0.111065 
        0 
       | 
       35 
 INDEX: SKAPOOR 
    NAME_IND 

从 sample 数据库中收集 db2look 信息: 

db2look -d sample -l -o storage.out 
db2look -d sample -e -a -m -t STAFF -o db2look.out 
db2look -d sample -f -fd -o config.out 

修改这些文件以使您连接 dummy 数据库,而非之前在上面 示例 1 中所连接的 sample 数据库。  
手工修改统计数据之一。在 db2look.out 文件中搜索下列语句(请注意,模式名、TABSCHEMA 和 INDSCHEMA 可能与您的具体情况不同): 

UPDATE SYSSTAT.INDEXES 
SET NLEAF=1, 
    NLEVELS=1, 
    FIRSTKEYCARD=35, 
    FIRST2KEYCARD=35, 
    FIRST3KEYCARD=-1, 
    FIRST4KEYCARD=-1, 
    FULLKEYCARD=35, 
    CLUSTERFACTOR=-1.000000, 
    CLUSTERRATIO=100, 
    SEQUENTIAL_PAGES=0, 
    DENSITY=0, 
    AVERAGE_SEQUENCE_GAP=0.000000, 
    AVERAGE_SEQUENCE_FETCH_GAP=0.000000, 
    AVERAGE_SEQUENCE_PAGES=0.000000, 
    AVERAGE_SEQUENCE_FETCH_PAGES=0.000000, 
    AVERAGE_RANDOM_PAGES=1.000000, 
    AVERAGE_RANDOM_FETCH_PAGES=0.000000, 
    NUMRIDS=35, 
    NUMRIDS_DELETED=0, 
    NUM_EMPTY_LEAFS=0 
WHERE INDNAME = ’NAME_IND’ AND INDSCHEMA = ’SKAPOOR ’ 
      AND TABNAME = ’STAFF’ AND TABSCHEMA = ’SKAPOOR ’; 

现在,将 FIRSTKEYCARD、FIRST2KEYCARD、FULLKEYCARD 和 NUMRIDS 从 35 修改为 37。现在保存 db2look.out 文件并运行这 3 个文件: 

db2 -tvf config.out > config_output.out 
db2 -tvf storage.out > storage_output.out 
db2 terminate 
db2stop 
db2start 
db2 -tvf db2look.out > db2look_output.out 

检查前两个文件 config_output.out 和 storage_output.out 的内容,以确保它们运行成功。现在,检查 db2look_output.out 文件的内容。您将看到下列更新语句失败了: 

UPDATE SYSSTAT.INDEXES SET NLEAF=1, NLEVELS=1, FIRSTKEYCARD=37, FIRST2KEYCARD=37 
, FIRST3KEYCARD=-1, FIRST4KEYCARD=-1, FULLKEYCARD=37, CLUSTERFACTOR=-1.000000, C 
LUSTERRATIO=100, SEQUENTIAL_PAGES=0, DENSITY=0, AVERAGE_SEQUENCE_GAP=0.000000, A 
VERAGE_SEQUENCE_FETCH_GAP=0.000000, AVERAGE_SEQUENCE_PAGES=0.000000, AVERAGE_SEQ 
UENCE_FETCH_PAGES=0.000000, AVERAGE_RANDOM_PAGES=1.000000, AVERAGE_RANDOM_FETCH_ 
PAGES=0.000000, NUMRIDS=37, NUMRIDS_DELETED=0, NUM_EMPTY_LEAFS=0 WHERE INDNAME = 
 ’NAME_IND’ AND INDSCHEMA = ’SKAPOOR ’ AND TABNAME = ’STAFF’ AND TABSCHEMA = ’SK 
APOOR ’ 
DB21034E  The command was processed as an SQL statement because it was not a 
valid Command Line Processor command.  During SQL processing it returned: 
SQL1227N  The catalog statistic "37" for column "FULLKEYCARD" is out of range 
for its target column, has an invalid format, or is inconsistent in relation 
to some other statistic. Reason Code = "8".  SQLSTATE=23521 

正如您可以看到的,上面用于索引 NAME_IND 的 UPDATE 语句失败了,因为 FULLKEYCARD 大于表的基数(CARD)。正如通过 db2look.out 文件中的下列更新语句可以看到的,CARD 是 35: 

UPDATE SYSSTAT.TABLES 
SET CARD=35, 
    NPAGES=1, 
    FPAGES=1, 
    OVERFLOW=0, 
    ACTIVE_BLOCKS=0 
WHERE TABNAME = ’STAFF’ AND TABSCHEMA = ’SKAPOOR ’; 

现在,再次以解释模式运行相同的查询: 

db2 "select name from staff where id=10 order by name" 

并生成访问计划。您将看到它是不同的: 

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

      Rows 
     RETURN 
     (   1) 
      Cost 
       I/O 
       | 
        1 
     TBSCAN 
     (   2) 
     12.972 
        1 
       | 
        1 
     SORT 
     (   3) 
     12.9708 
        1 
       | 
        1 
     TBSCAN 
     (   4) 
     12.9682 
        1 
       | 
       35 
 TABLE: SKAPOOR 
      STAFF 

该示例显示,如果在表上发生 WRITE 活动时运行 RUNSTATS,统计数据就可能与本示例中的不一致。因此,用于更新统计数据的 UPDATE 语句可能失败并产生 SQL1227N 错误消息。所有的 UPDATE 语句都运行成功十分重要,如果存在不一致性,就应该进行修理并重新运行。本例中,解决方案是将 KEYCARDS 和 NUMRIDS 从 37 重新修改为 35。 
相关阅读