db2 sql语句优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了db2 sql语句优化相关的知识,希望对你有一定的参考价值。

select
a.entrustdate,a.busseqno,a.bustype,a.vouchno,a.sendbank,a.payeracc,a.payername,a.payeraddr,a.currency,a.amount,a.payeeacc,a.payeename,a.recvbank,a.payeeaddr,a.postscript,a.printcnt,a.agentserialno,a.tradebusistep||a.tradestatus,b.drbankno,b.crbankno,b.bdstmagno,b.bondco,b.npamt,b.bondint,b.adenamg,b.refrtset,b.rendat,b.reint,b.dcflag,b.txnbatchno,b.bussubtype,g.recvbank,g.payeeacc,g.payeename,h.banksysseq
from afa_maintransdtl a
left join ext_transbook b on a.workdate=b.workdate and a.agentserialno=b.agentserialno
left join ext_insusbook as g on a.workdate=g.oworkdate and a.agentserialno=g.oagentserialno
left join afa_mainaction as h on a.workdate=h.workdate and a.agentserialno=h.agentserialno and a.tradestep=h.tradestep
where
a.sysid='000001'
and
(
( a.brno='320099900' and a.sysid='000001' and a.mbflag='1' and a.workdate between '20120325' and '20120331' and (
(a.tradebusistep='U' and a.tradestatus='1') or (a.tradebusistep='V' and a.tradestatus='1')
)
)
or
(
a.workdate<='20120331' and (a.workdate,a.agentserialno) in (select f.oworkdate,f.oagentserialno from ext_insusbook as f where f.sysid='000001' and f.recvbank='402301099998' and f.status='1' and f.workdate>='20120325' and f.workdate<='20120331' and f.mbflag='1')
)
) and a.agentserialno>'0' order by a.agentserialno asc fetch first 6 rows only
这条语句执行花了17秒,其中a表的brno是索引,a表的sysid是索引,a表的workdate是索引,求高手帮忙优化下
a表的数据量大概在200万左右

b/g/h三个表的workdate有索引么?另外,1.如果可能最好将所有联表用的字段都进行索引,2.(workdate,agentserialno)可以考虑二维索引,前提是空间足够的话,这样效率提高会非常明显。追问

其他几个表都分别有索引也用到了,主要是后面那段workdate,agentserialno in f表的时候,效率太低了

追答

如果workdate,agentserialno in f那块儿前面是and的话,倒是可以用给f加索引然后在开头把f也连表连进来。可惜这里是or,确实挺难办的。推荐1.如果查询频繁,而f表相对稳定,可以建立f的临时表或视图;2.可以把整个查询根据那个or分成两个查询,直接在外层,甚至用存储过程(存储函数)来合并它们。

参考技术A 麻.烦`采纳.··.·`··^ 参考技术B select name from user. 给分吧 参考技术C 看能不能把这个语句的执行计划图给出来。看你的语句你试试能不能把left join取消。

【DB2】SQL优化

参考技术A

于我来说,我喜欢技术,不偏执于某一类开发语言,愿意花时间精力去解决问题。

1.去除在谓词列上编写的任何标量函数

优化前:(耗时3.1s)

优化后:(耗时0.922s)

总结:

DB2可以选择使用START_DATE上的列索引,但是在列上使用了函数后,DB2就无法使用列索引了,从而导致查询效率变低。

2.去除在谓词列上编写的任何数学运算

优化前:(耗时10.265)

优化后:(耗时3.39s)

总结:

DB2查询时候,会优先选择列CONTRACT_AMT上的索引,如果直接对列CONTRACT_AMT应用数学运算,DB2就无法使用索引了。一定要做到:列本身(不加数学运算)放在操作符的一边,而所有的计算都放在另外一边。

3.SQL语句中指定查询列

优化前:(耗时13.15s)

优化后:(耗时2.922s)

总结:

如果Select包含不需要的列,优化工具会选择Indexonly=’N’,这会强制DB2必须进入数据页来得到所请求的特定列,这就要求更多的I/O操作,梁歪,这些多余的列可能是某些排序的部分,这样一来就需要和传递一个更大的排序文件,相应的会使排序成本更高。

4.尽可能不使用distinct

优化前:(耗时0.687s)

优化后:(耗时0.437s)

总结:

在测试distinct与group by性能的过程中,在列CST_ID上添加索引后,发现group by 确实比distinct快一些,但是在数据分布比较离散的情况下使用group by ,比较集中的情况下使用distinct.表数据量较少的情况随便使用哪个都一样, 不管选择谁,都要建立索引

5.Exists、in、not in 、not exists的使用场景选择

5.1 in跟exists的区别:

例如:表A(小表),表B(大表)

优化前:(耗时1.93s)

优化后:(耗时1.125s)

相反的,

优化前:(耗时1.9s)

优化后:(耗时1.0s)

总结:

in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。 如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in;

简称:子大Exists,子小in

5.2 not in 与 not exists区别:

如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快。

6.尽可能使用union all来代替union

优化前:(耗时15.344s)

优化后:(耗时2.719s)

总结:

在union中,DB2最后会自动执行一个排序来消除重复值,这样是很耗费资源的,所以在不需要去重复的情况下,尽可能使用UNION ALL 代替union

N.模板

优化前:(耗时3.1s)

优化后:(耗时0.922s)

总结:

以上是关于db2 sql语句优化的主要内容,如果未能解决你的问题,请参考以下文章

【DB2】SQL优化

Db2 数据库 SQL 语句性能调优 8 个技巧

db2 优化基础 查询运行时间最长的SQL

数据库优化

MySQL执行计划

如何做SQL优化?优化SQL语句,提高SQL查询效率。Effective MySQL之SQL语句最优化