DB2优化之:db2expln的使用及实例分析

1、准备实验环境

我们创建了一个模拟tpch(数据库工业标准测试,http://www.tpc.org/tpch/specs.asp)测试的数据库,库中一共有3张数据表,分别是:

part      产品部件表

supplier  供应商表

partsupp  产品供应商关联表

其中part表中含有200000条数据,partsupp表中含有800000条数据,supplier表中含有10000条数据

1)  我们为如上的3张表分别建立如下的索引:

create index part_idx1 on tpcd.part(p_partkey,p_size);

create index partsupp_idx1 on tpcd.partsupp(ps_partkey, ps_supplycost, ps_suppkey);

create index supp_idx1 on tpcd.supplier(s_suppkey);

 

 

2)  建立索引后,我们收集一下相关的统计信息,在db2cmd中执行如下的命令:

runstats on table tpcd.part with distribution and detailed indexes all;

runstats on table tpcd.partsupp with distribution and detailed indexes all;

runstats on table tpcd.supplier with distribution and detailed indexes all;

 

 

分别对PART,  PARTSUPP,  SUPPLIER运行以下命令,确保runstats已经成功执行:

db2 “select card,npages,stats_time from syscat.tables where tabname=’PART’”

 

CARD                 NPAGES               STATS_TIME

-------------------- -------------------- -----------------------------------------------------------

 200000                 7616               2008-08-21-17.20.22.828000

 

 

其中,CARD为该表的记录数,NPAGES为该表所占有的存储空间(页数)STATS_TIME为收集统计信息的时间。



2、发现问题

1)  我们有如下的一个SQL语句:

 

select

    count(*)

from

         tpcd.part,

         tpcd.partsupp,

         tpcd.supplier

where

         p_partkey = ps_partkey

         and s_suppkey = ps_suppkey

    and p_size = 30

         and ps_suppkey = 9988@

 

 

目前,该SQL的运行速度不理想,我们希望通过调优提高这个SQL语句的执行效率。

首先,我们为了记录这条查询语句执行的时间,运行如下SQL文件,记录一个时间:

文件名:lab.sql

values current timestamp@

 

select       

  count(*)

from

  tpcd.part,       

  tpcd.partsupp,        

  tpcd.supplier

where       

  p_partkey = ps_partkey 

  and s_suppkey = ps_suppkey       

  and p_size = 30     

  and ps_suppkey = 9988@

 

values current timestamp@

 

 

db2cmd中运行:

db2 -td@ -vf  lab.sql

 

 

得到结果如下:

1

--------------------------

2009-01-04-15.09.25.281000

条记录已选择。

 

select count(*) from tpcd.part, tpcd.partsupp, tpcd.supplier where p_partkey = ps_partkey and s_suppkey = ps_suppkey an p_size = 30 and ps_suppkey = 9988

1

-----------

1

  1 条记录已选择。

 

values current timestamp

1

--------------------------

2009-01-04-15.09.33.359000

 

  1 条记录已选择。

 

 

通过前后时间对比,我们发现这个SQL运行了大约6秒钟(不同的机器性能可能有差异)



3、分析问题

1)  为了了解这个SQL的执行过程,我们开始分析它的执行计划,在db2cmd中运行:

db2expln -d tpcd -f lab.sql -t -z @ -g > lab-before.exp

 

可以用文本编辑器打开lab-before.exp,下面,我们详细解读其中的执行计划:如图1所示

 

分析:执行计划是倒树状的结构,首先对part表、partsupp表和supplier表进行索引扫描,然后对partpartsupp表的索引扫描结果进行NLJOIN(嵌套循环连接),再将结果与supplier表的索引扫描结果进行HSJOINHASH连接),再进行排序,最后返回查询结果。

其中黄色标记部分,我们发现执行part表的索引扫描花费较大(1261.42个单位),且扫描结果(3810行)与我们的最终期望结果(1)差距较大,执行NLJOIN的花费(7443.881261.4215.1451=6167.31个单位),因此我们认为这里partpartsupp表建立的索引是影响查询效率的因素。



4、解决问题

1)  在仔细分析的问题之后,我们尝试来解决这个问题,我们规划了一个新的索引方案,我们建立新的索引:

drop index part_idx1;

create index part_idx1 on tpcd.part(p_size,p_partkey);

drop index partsupp_idx1;

create index partsupp_idx1 on tpcd.partsupp(ps_suppkey,ps_partkey, ps_supplycost );

drop index supp_idx1;

create index supp_idx1 on tpcd.supplier(s_suppkey);

 

 

我们改变了part表和partsupp表的索引顺序

2)  建立索引后,我们再收集一下相关的统计信息,在db2cmd中执行如下的命令:

runstats on table tpcd.part with distribution and detailed indexes all;

runstats on table tpcd.partsupp with distribution and detailed indexes all;

runstats on table tpcd.supplier with distribution and detailed indexes all;

 

 

3)  下面,我们再执行一下原来的SQL,在db2cmd中执行:

db2 connect to tpcd

db2 –td@ -vf  lab.sql

1

--------------------------

2009-01-04-16.02.45.078000

  1 条记录已选择。

 

select count(*) from tpcd.part, tpcd.partsupp, tpcd.supplier where p_partkey = ps_partkey and s_suppkey = ps_suppkey an p_size = 30 and ps_suppkey = 9988

1

-----------

1

  1 条记录已选择。

 

values current timestamp

1

--------------------------

2009-01-04-16.02.45.218000

 

  1 条记录已选择。

 

 

 

通过前后时间对比,我们发现这次,这个SQL运行时间在1秒之内 (不同的机器性能可能有差异)

4)  为了进一步分析这个SQL的执行过程,我们再分析一下SQL的执行计划:

db2cmd中运行:

db2expln -d tpcd -f lab.sql -t -z @ -g > lab-after.exp

 

 

 

可以用文本编辑器打开lab-after.exp,下面,我们详细解读这个执行计划,如图2所示

 

从执行的总花费(84.817)上我们可以明显的看到优化后的效果。



5、解决方案分析

我们来看实验Sql语句的谓词部分:

p_partkey = ps_partkey

   and s_suppkey = ps_suppkey

     and p_size = 30

         and ps_suppkey = 9988@

 

DB2sql优化器在执行查询sql语句,根据谓词进行表连接查询,并不依赖于where条件中谓词的顺序,而是根据所建索引来进行先后顺序的连接。

我们再来看优化前的索引:

create index part_idx1 on tpcd.part(p_partkey,p_size);

create index partsupp_idx1 on tpcd.partsupp(ps_partkey, ps_supplycost, ps_suppkey);

create index supp_idx1 on tpcd.supplier(s_suppkey);

 

1)我们目标是尽量增大第一次或前几次join的数据量缩小幅度,所以首先要进行小表的索引扫描和连接。而这里,从业务角度来说,把业务主键放到索引的第一个位置是有意义的,但是对于优化器来说,这毫无意义。优化器会根据索引优化器会首先选择谓词:p_partkey = ps_partkey partpartsupp进行NLJOIN,而这两个表是数据量相对大的表。

2NLJOIN中外表只扫描一次,内表扫描N次,所以内表要尽量的小一些。而这里的内表partsupp800000条数据。

我们期望优化器做如下处理:

1)优化器首先根据谓词p_size = 30 ps_suppkey = 9988@进行索引扫描,缩小数据范围。

2)优化器根据谓词s_suppkey = ps_suppkeysupplierpartsupp进行表的NLJOIN。内表(partsupp)是数据量较小的一个表

所以,我们要将p_sizeps_suppkey的索引提前,建立如下索引

create index part_idx1 on tpcd.part(p_size,p_partkey);

create index partsupp_idx1 on tpcd.partsupp(ps_suppkey,ps_partkey, ps_supplycost );

create index supp_idx1 on tpcd.supplier(s_suppkey);

 

 


6、总结

使用db2expln解释工具,能够得到DB2 Sql优化器的详细Sql执行计划,通过其中的花费我们可以结合sql语句及表、索引、连接的结构进行分析,发现并定位问题,然后对sql进行改进,达到优化的目标。


转载于:https://my.oschina.net/goopand/blog/404551

来源:https://my.oschina.net/goopand/blog/404551


智能推荐

【DB2-HADR】使用 DB2 HADR 选择用于灾难恢复的 SUPERASYNC 模式

简介和背景 HADR 是一个通过数据复制提供高可用性和灾难恢复的 DB2 功能。在启用该功能时,可以将主要数据库数据日志实时传送到备用数据库。备用数据库继续重放已收到的日志,以便与主要数据库保持同步。 从 DB2 V9.5 Fix Pack 8 和 DB2 V9.7 Fix Pack 5 开始,SUPERASYNC 被指定为hadr_syncmode,这样主要数据库在任何情况下都不会受阻。 本文将...

DB2使用TransactionScope报错的解决方法

DB2使用TransactionScope报如下错误: IBM.Data.DB2.DB2Exception:ERROR [58005] [IBM][DB2/LINUXX8664] SQL0998N 在事务或试探性处理期间出错。原因码:“16”。子代码:“2-FFFFFFFF8004D026” 原因:没有配置MSDTC 配置步骤: 1.Window开始...

安装完DB2使用db2命令报bash: db2: command not found...

安装完DB2后一切正常,可就是切换换db2inst1用户后执行#db2报一下错误 [root@SCdatastage ~]# su - db2inst1 Last login: Tue Sep  4 11:02:12 CST 2018 on pts/0 -sh-4.2$ db2 bash: db2: command not found... -sh-4.2$  一般产生此错误的...

《让DB2跑得更快——DB2内部解析与性能优化》

《让DB2跑得更快——DB2内部解析与性能优化》 DB2数据库领域的精彩强音,DB2技巧精髓的热心分享,资深数据库专家牛新庄、干毅民、成孜论、唐志刚联袂推荐! 本书作者在DB2China数据库论坛担任热点讨论版块版主,主持多次热点讨论以及专家现场诊断,擅长DB2数据库及相关产品的性能调优及故障分析,对DB2技能及实践经验有多年积累,并且近年来与多位业界专家一直在积极推动DB...

DB2的Sequence 对象(1)

数字生成问题    过去的许多应用程序都需要能够生成序号(例如获取下一个可用的帐号)。问题是该工作通常是通过用单个控制表存储这些数字,然后用可重复读(Repeatable Read)的 SELECT MAX 在随后的 INSERT 中检索并使用该数字来完成的。常常有多个事务需要使用该表,而这就导致了应用程序中无法解决的单点竞争。这是由于每次只有一个事务可以检索下一值,...

猜你喜欢

DB2系统结构的理解

下图描述了DB2的进程模型,长方形代表处理进程,椭圆形代表处理线程,DB2的主进程是db2sysc,在这个处理进程下有许多线程,最主要的线程也是叫db2sysc,这个主要的线程派生了其他子线程。当一个远程的应用程序比如采用sql connect语句链接服务器时,通讯协议的远程监听器将接收这个请求,并联系db2agent,agent是一个代表DB2实现一些小操作的处理程序,当发出请求的应用程序是本地...

DB2的下载、安装

由于近期需要用DB2数据库,之前又没有接触过,这里记录一下安装过程。 下载地址,"IBM DB2 Express-C is a free, unlimited-use database for relational and XML data",所以选择下载了Express-C版本,没有IBM账号的需要进行一**册,我这里选择了Windows版本进行下载、安装。 下载完成后,解压...

db2的启动命令

想重启db2库,直接使用db2stop命令,执行报错 这样停不掉,因为有连接在上面 查看连接 db2 list applications show detail 发现有很多连接,连接在bpfdb5这个库上面 杀掉所有的连接 db2 force application all 再次检查连接 发现没有连接了 再次停实例 启动实例 检查实例下的所有库 db2 list db directory 检查对应...

如何创建你的ico图标(一个含有多种尺寸的ico)

一、下载ps下能存ico格式的插件 因为我们要在Photoshop中创建这个图标,所以,首先要下载能将图片保存为.ico格式的Photoshop插件。Photoshop本身是不支持将图片保存为.ico格式的,有了这个插件,你才能轻松的将做好的图片保存为我们所需要的格式。 下载好以后,安装到你相应的文件夹中一般来说是你ps安装位置的我的是7.0,我给放这里了Program Files\Adobe\P...

关于公众号内容的几点说明

写在前面,博主基于自己的工作情况及阶段性学习总结,将自己的感悟和历程记录下来。欢迎大家关注,和博主一起共同进步。 本公众号的每篇文章都是基于博主自己的理解和实践得出的一点感悟,在此记录下来,方便以后学习。 号内文章全部坚持原创,所以文章更新速度不能按时,但一定保证文章的质量。 号内文章主要分为三部分 源码分析(目前业界优秀的开源框架源码分析,目前在做Spring源码分析持续更新) 分布式杂谈(由于...

问答精选

Render Section Without reloading Layouts MVC

I'm using Two layouts 1- Main Layout : "~/Views/Shared/_Layout.cshtml" 2- Left Side layout "~/Views/Shared/_LeftSide.cshtml" (this view also contains main layout) In left Side Layo...

Different results using numpy.in1d() with an array and with its single elements

I'm writing a code in Python and I'm having a few problems. I have two arrays, let's say A and B, both of them containing IDs. A has all IDs, and B has IDs belonging to a group. What I'm trying to do ...

How can I pass multiple std::filesystem options?

Here is my recursive copy line: I want to have it be both recursive and update existing. So something like: The above is invalid. How do I achieve this? Thank you. From https://en.cppreference.com/w/c...

RFC 4175 support in ffmpeg?

As of today, is RFC 4175 (aka SMPTE 2110-20) currently supported in the released version of ffmpeg (4.1)? Surfing the web I am only able to find these two references: https://patchwork.ffmpeg.org/patc...

How to add custom list item in action bar searchview

I've added a searchView to the toolbar, and added the search suggestions. The problem is I want to add a custom list-item to the search suggestions as the last item to clear the suggestions(search his...

相关问题

相关文章

热门文章

推荐文章

相关标签

推荐问答