`

提高DB2查询性能的常用方法(二)

    博客分类:
  • DB2
阅读更多

下面我们将从三个方面介绍一些提高查询性能的方法。

  创建索引

 

  根据查询所使用的列建立多列索引

 

  建立索引是用来提高查询性能最常用的方法。对于一个特定的查询,可以为某一个表所有出现在查询中的列建立一个联合索引,包括出现在 select 子句和条件语句中的列。但简单的建立一个覆盖所有列的索引并不一定能有效提高查询,因为在多列索引中列的顺序是非常重要的。这个特性是由于索引的 B+ 树结构决定的。一般情况下,要根据谓词的选择度来排列索引中各列的位置,选择度大的谓词所使用的列放在索引的,把那些只存在与 select 子句中的列放在索引的最后。譬如清单 5 中的查询:

 


  清单5. 索引中的谓词位置        

 

 


  select add_date
from temp.customer
where city = 'WASHINGTON'
and cntry_code = 'USA';

 

  对于这样的查询可以在 temp.customer 上建立 (city,cntry_code,add_date) 索引。由于该索引包含了 temp.customer 所有用到的列,此查询将不会访问 temp.customer 的数据页面,而直接使用了索引页面。对于包含多列的联合索引,索引树中的根节点和中间节点存储了多列的值的联合。这就决定了存在两种索引扫描。回到清单 5 中的查询,由于此查询在新建索引的第一列上存在谓词条件,DB2 能够根据这个谓词条件从索引树的根节点开始遍历,经过中间节点最后定位到某一个叶子节点,然后从此叶子节点开始往后进行在叶子节点上的索引扫描,直到找到所有满足条件的记录。这种索引扫描称之为 Matching Index Scan。但是如果将 add_date 放在索引的第一个位置,而查询并不存在 add_date 上的谓词条件,那么这个索引扫描将会从第一个索引叶子节点开始,它无法从根节点开始并经过中间节点直接定位到某一个叶子节点,这种扫描的范围扩大到了整个索引,我们称之为 Non-matching Index Scan。图 5 显示了 DB2 根据不同索引生成的存取计划。

 


  图5. 根据不同索引生成的存取计划

 

  根据不同索引生成的存取计划

 

  根据不同索引生成的存取计划

 

  根据条件语句中的谓词的选择度创建索引

 

  因为建立索引需要占用数据库的存储空间,所以需要在空间和时间性能之间进行权衡。很多时候,只考虑那些在条件子句中有条件判断的列上建立索引会也会同样有效,同时节约了空间。譬如清单 5 中的查询,可以只建立 (city,cntry_code) 索引。我们还可以进一步地检查条件语句中的这两个谓词的选择度,执行清单 6 中的语句检查谓词选择度:

 

  清单 6.检查谓词选择度                
             


   Queries:
1. select count(*) from temp.customer
where city = 'WASHINGTON'
and cntry_code = 'USA';
2. select count(*) from temp.customer
where city = 'WASHINGTON';
3. select count(*) from temp.customer
where cntry_code = 'USA';
Results:
1. 1404
2. 1407
3. 128700


  选择度越大,过滤掉的记录越多,返回的结果集也就越小。从清单 6 的结果可以看到,第二个查询的选择度几乎有和整个条件语句相同。因此可以直接建立单列索引 (city),其性能与索引 (city,cntry_code,add_date) 具有相差不多的性能。表 1 中对两个索引的性能和大小进行了对比。

 


  表 1. 两个索引的性能和大小对比

 

 

    
索引                 查询计划总代价   索引大小
cust_i1(city,cntry_code,add_date) 28.94 timerons   19.52M
cust_i3(city)           63.29 timerons    5.48M

 

  从表 1 中可以看到单列索引 (city) 具有更加有效的性能空间比,也就是说占有尽可能小的空间得到尽可能高的查询速度。

 

  避免在建有索引的列上使用函数

 

  这是一个很简单的原则,如果在建有索引的列上使用函数,由于函数的单调性不确定,函数的返回值和输入值可能不会一一对应,就可能存在索引中位置差异很大的多个列值可以满足带有函数的谓词条件,因此 DB2 优化器将无法进行 Matching Index Scan,更坏的情况下可能会导致直接进行表扫描。图 6 中对比了使用 function 前后的存取计划的变化。

 

  使用function前后的存取计划的变化

 

  
  图6. 使用 function 前后的存取计划的变化
 

 

  那些需要被排序的列上创建索引

 

  这里的排序不仅仅指 order by 子句,还包括 distinct 和 group by 子句,他们都会产生排序的操作。由于索引本身是有序的,在其创建过程中已经进行了排序处理,因此在应用这些语句的列上创建索引会降低排序操作的代价。这种情况一般针对于没有条件语句的查询。如果存在条件语句,DB2 优化器会首先选择出满足条件的纪录,然后才对中间结果集进行排序。对于没有条件语句的查询,排序操作在总的查询代价中会占有较大比重,因此能够较大限度的利用索引的排序结构进行查询优化。此时可以创建单列索引,如果需要创建联合索引则需要把被排序的列放在联合索引的第一列。图 7 对比了清单 7 中的查询在创建索引前后的存取计划。

 


  清单7. 查询在创建索引前后的存取计划

 

              

  select distinct add_date from temp.customer;

 

  在创建索引前后的存取计划

 


  图7. 在创建索引前后的存取计划

 

  在创建索引前后的存取计划
 
  从图 7 中我们可以看到在没有索引的情况下 SORT 操作是 24751.69 timerons,但是有索引的情况下,不再需要对结果集进行排序,可以直接进行 UNIQUE 操作,表中显示了这一操作只花费了 2499.98 timerons.

 

  图8对比了清单 8 中的查询在创建联合索引前后的存取计划,从中可以更好的理解索引对排序操作的优化。

 

  清单8. 查询示例

 

 


               
select cust_name from temp.customer order by add_date;

 

  创建联合索引前后的存取计划

 


  图8. 创建联合索引前后的存取计划

 

  索引的 B+ 树结构决定了索引 temp.cust_i5 的所有叶子节点本身就是按照 add_date 排序的,所以对于清单 8 中的查询,只需要顺序扫描索引 temp.cust_i5 的所有叶子节点。但是对于 temp.cust_i6 索引,其所有叶子节点是按照 cust_name 排序,因此在经过对索引的叶子节点扫描获得所有数据之后,还需要对 add_date 进行排序操作。

 

  合理使用include关键词创建索引

 

  对于类似下面的查询 :

 

  清单9. 查询示例               

 

 


select cust_name from temp.customer
where cust_num between '0007000000' and '0007200000'

 

  在第一点中我们提到可以在 cust_num 和 cust_name 上建立联合索引来提高查询性能。但是由于 cust_num 是主键,可以使用 include 关键字创建唯一性索引:

 

 


create unique index temp.cust_i7 on temp.customer(cust_num) include (cust_name)

 

  使用 include 后,cust_name 列的数据将只存在于索引树的叶子节点,并不存在于索引的关键字中。这种情况下,使用带有 include 列的唯一索引会带来优于联合索引的性能,因为唯一索引能够避免一些不必要的操作,如排序。对于清单 9 中的查询创建索引 temp.cust_i7 后存取计划的代价为 12338.7 timerons,创建联合索引 temp.cust_i8(cust_num,cust_name) 后的代价为 12363.17 timerons。一般情况下当查询的 where 子句中存在主键的谓词我们就可以创建带有 include 列的唯一索引,形成纯索引访问来提高查询性能。注意 include 只能用在创建唯一性索引中。

 

  指定索引的排序属性

 

  对于下面用来显示最近一个员工入职的时间的查询:

 

 


select max(add_date) from temp.employee

 

  很显然这个查询会进行全表扫描。查询计划如图 9.a:

 

  图 9. 查询计划

 

  查询计划

 

  显然我们可以在 add_date 上创建索引。根据下面的命令创建索引后的查询计划如图 9.b。

 

 

create index temp.employee_i1 on temp.employee(add_date)

 

  这里存在一个误区,大家可能认为既然查询里要取得的是 add_date 的最大值,而我们又在 add_date 上建立了一个索引,优化器应该知道从索引树中直接去寻找最大值。但是实际情况并非如此,因为创建索引的时候并没有指定排序属性,默认为 ASC 升序排列,DB2 将会扫描整个索引树的叶子节点取得所有值后,然后取其最大。我们可以通过设置索引的排序属性来提高查询性能,根据下面的命令创建索引后的查询计划如图 9.c。

 

 


create index temp.employee_i1 on temp.employee(add_date desc)

 

  对于降序排列的索引,DB2 不需要扫描整个索引数的叶子节点,因为第一个节点便是最大的。我们同样可以使用 ALLOW REVERSE SCANS 来指定索引为双向扫描具有和 DESC 近似的查询性能。ALLOW REVERSE SCANS 可以被认为是 ASC 和 DESC 的组合,只是在以后数据更新的时候维护成本会相对高一些。

 

  如果无法改变索引的排序属性,但是我们具有额外的信息,该公司每个月都会有新员工入职,那么这个查询就可以改写成:

 

 


select max(add_date) from temp.employee where add_date > current timestamp - 1 month

 

  这样通过限定一个查询范围也会有效地提高查询性能。

分享到:
评论

相关推荐

    DB2高性能最优方法

    DB2高性能最优方法是数据库管理员和IT专业人员在管理和优化大型数据库...对DB2性能优化的深入理解和实践,是IT专业人士不可或缺的技能。在实际工作中,结合具体环境和需求,灵活运用这些方法,才能最大化DB2的潜力。

    DB2 通用数据库性能调整的常用方法

    ### DB2 通用数据库性能调整的常用方法 #### 统计值更新——runstats 在DB2数据库中,保持统计信息的最新状态是确保查询优化器能够做出最佳决策的关键。统计信息反映了数据库中数据分布的特性,如表的行数、各列值...

    DB2数据库性能调整和优化

    DB2数据库是IBM公司开发的一款关系型数据库管理系统,广泛应用于企业级数据存储和管理。...《DB2数据库性能调整和优化(第2版).pdf》这本书应该会提供更详尽的指导和案例分析,是学习和提升DB2性能优化技能的重要资源。

    DB2 数据库常用命令

    在DB2中,`RUNSTATS`是一个重要的实用程序,用于收集表和索引的统计信息,这些信息对优化查询计划和提高查询性能至关重要。当数据库的大小或数据分布发生变化时,运行`RUNSTATS`可以确保数据库管理系统(DBMS)拥有...

    db2性能调优之Sql执行监控.doc

    《DB2性能调优之SQL执行监控》 在数据库管理领域,DB2作为一款强大的关系型数据库管理系统,其性能调优是一项至关重要的任务。本文将深入探讨如何通过监控SQL执行来提升DB2的性能,帮助数据库管理员更好地理解和...

    linux下DB2常用命令

    Linux 下 DB2 常用命令 DB2 是一个 relation database management system(关系数据库管理系统),广泛应用于企业级的数据存储和管理中...这些命令可以帮助用户快速管理和维护 DB2 数据库,提高数据库的性能和安全性。

    db2数据库sql语句大全

    这有助于提高基于`column1`查询时的速度。 #### 7. 运行统计分析 ```sql runstatsontable<> for index <> shrlevel reference; ``` 此命令用于运行统计分析,它针对表`<>`及其索引`<>`执行,并设置共享级别为`...

    DB2常用命令集

    ### DB2常用命令集 #### 1. 停止 DB2 实例 - **命令**: `db2stop` - **描述**: 该命令用于停止正在运行的DB2实例。 - **注意事项**: 如果实例中有未完成的事务或连接,`db2stop`会等待这些事务完成或超时后自动...

    DB2性能安全文件

    ### DB2性能安全知识点概述 #### 一、SERV_ID等常用字段的长度为何需要统一? 在实际生产环境中,为了确保数据的一致性和查询效率,DBA常常会规范某些常用字段(如`SERV_ID`)的长度。这样做主要是为了减少因字段...

    基于ORACLE与DB2的数据性能 调整和优化问题研究

    3.2 提高 DB2 查询性能的常用方法 DB2的优化包括使用索引、优化查询语句、启用并行执行、设置合适的统计信息等。例如,通过调整SQL语句的JOIN顺序,可以显著降低查询成本。 4. 性能分析和调优的命令和工具 4.1 ...

    DB2 UDB AS400版数据性能和查询优化

    本文档主要针对DB2 UDB在AS/400上的应用,重点介绍如何进行数据性能优化和查询优化,旨在帮助用户提高数据库运行效率,减少响应时间,提升用户体验。 #### 二、关键概念与术语 1. **AS/400**: IBM推出的一种集成化...

    DB2常用命令,DB2 v8数据库基础

    例如,分区功能允许将大型表分散到多个物理设备上,以提高查询性能。 文档"03_DB2 V8数据库基础.doc"可能涵盖了DB2 v8的基础架构、安装步骤、实例创建和管理、安全性配置等内容。而"02_DB2 常用命令.doc"则详细解释...

    db2数据库常用命令汇总

    `db2 create index <索引名> on <表名>(<字段名>)`:为表创建索引,提高查询速度。 `db2 drop index <索引名> on <表名>`:删除已有的索引。 8. **权限管理** `db2 grant <权限> on <对象> to <用户>`:赋予用户...

    提高DB2存储过程性能和健壮性.txt

    ### 提高DB2存储过程性能和健壮性的关键策略 在数据库管理与优化领域,DB2作为IBM的一款高性能关系型数据库管理系统,其存储过程的优化是确保应用响应速度与数据处理效率的关键。以下是对如何提高DB2存储过程性能和...

    Db2中的常用命令和导入导出

    本文将详细介绍DB2中常用的命令及其导入导出方法。 #### 常用命令 ##### 启动与停止数据库服务 - **db2start**:启动当前的DB2数据库实例。 - **db2stop**:停止当前的DB2数据库实例。 - **db2stop force**:强制...

    DB2数据库常用命令手册

    - 重新组织表可以提高查询性能,运行统计信息有助于优化查询计划。 #### 十、导出数据 **命令:** - `db2 export to <file_path> of del select * from <table_name>`:将数据导出到指定文件。 **注意事项:** - `...

    DB2学习资料以及常用命令

    #### 二、DB2常用命令详解 ##### 1. 数据库快照获取(db2getsnapshotforlocksonmasa) ``` db2getsnapshotforlocksonmasa>zyl.out ``` 此命令用于获取数据库masa上的锁信息快照,并将结果输出到文件zyl.out。锁...

    db2 常用命令集合

    - `db2 reorg table ydd`:整理表`ydd`的空间,以提高查询性能。 - `db2 runstats on table ydd with distribution and indexes all`:收集统计信息并分析表`ydd`的数据分布,以优化查询计划。 #### 七、导出与导入...

    IBM db2 常用命令大全

    缓冲池是 DB2 中的一个重要概念,用于提高数据库的性能。下面是创建缓冲池的命令: `create bufferpool ibmdefault8k IMMEDIATE SIZE 5000 PAGESIZE 8 K ;` `create bufferpool ibmdefault16k IMMEDIATE SIZE 5000...

    DB2 常用命令汇总

    在IT行业中,DB2作为IBM的一款高性能关系型数据库管理系统,其广泛应用于企业级数据处理场景。对于初学者而言,掌握DB2的基本命令是入门的关键。以下是从给定文件中提取并详细阐述的DB2常用命令知识点: ### 1. ...

Global site tag (gtag.js) - Google Analytics