提高DB2查询性能的常用方法
2010-02-16 14:59:59 来源:WEB开发网这里存在一个误区,大家可能认为既然查询里要取得的是 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
这样通过限定一个查询范围也会有效地提高查询性能。
索引和表的维护
重新组织索引
随着数据的不断删除,插入和更新,索引页会变得越来越零散,索引页的物理存储顺序不再匹配其逻辑顺序,索引结构的层次会变得过大,这些都会导致索引页的预读取变得效率低下。因此,根据数据更新的频繁程度需要适当的重新组织索引。可以使用REORG INDEXES命令来重新组织索引结构,也可以删除并重新创建索引达到相同的目的。同样的,对表进行重新组织也会带来性能的改善。
重新组织某一个表的所有索引的命令如下:REORG INDEXES ALL FOR TABLE table_name。
重新组织一个表的数据的命令如下,在下面的命令还可以为其指定一个特定的索引,REORG命令将会根据这个索引的排序方式重新组织该表的数据。
REORG TABLE table_name INDEX index_name。
重新收集表和索引的统计信息
和在2.1中提到的原因类似,当一个表经过大量的索引修改、数据量变化或者重新组织后,可能需要重新收集表以及相关索引的统计信息。这些统计信息主要是关于表和索引存储的物理特性,包括记录数目,数据页的数目以及记录的平均长度等。优化器将根据这些信息决定使用什么样的存取计划来访问数据。因此,不能真实反映实际情况的统计信息可能会导致优化器选择错误的存取计划。收集表及其所有索引的统计信息的命令如下:RUNSTATS ON TABLE table_name FOR INDEXES ALL。
上述两个命令具有复杂的参数选择,用户可以参阅 DB2 Info Center 来根据实际情况使用这两个命令。
修改查询
合理使用NOT IN和NOT EXISTS
一般情况下 NOT EXISTS 具有快于 NOT IN 的性能,但是这并不绝对。根据具体的数据情况、存在的索引以及查询的结构等因素,两者会有较大的性能差异,开发人员需要根据实际情况选择适当的方式。
譬如下面的查询:
清单10.查询示例
表结构:temp.customer(cust_num) 主键:cust_num
表结构:temp.contact(cnt_id,cust_num) 主键:cnt_id
表结构:temp.contact_detail(cnt_id,address,phone) 主键:cnt_id
查询 :
select cust_num
from temp.customer cust
where not exists (select 1 from temp.contact cont
here cust.cust_num = cont.cust_num)
更多精彩
赞助商链接