解析Oracle数据扫描 Oracle SQL查询优化 引导局部范围数据扫描的方法(7)

发表于:2013-2-26 09:53

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:javacoffe    来源:51Testing软件测试网采编

通过编写PL/SQL函数实现局部范围扫描

  通过Oracle提供的PL/SQL编程语言,可以实现创建过程化SQL函数。在函数中不仅可以存在一个以上的SQL,而且还可以存在多样化的运算、条件处理、循环执行等语句。它依据外部所接受的值或固定的常量来执行必要的数据处理,并返回一个最终的处理结果。因此,我们可以通过编写函数,来处理复杂全局数据范围的运算,并通过函数将这些操作包装起来,从而避免向优化器提供选择使用全局范围扫描的机会,以确保语句按照局部范围扫描来执行。

  函数的处理特点是,每次函数只会返回一个处理结果,同时每次只处理对象集合中的一行数据,因此当需要获得多个结果时就必须反复执行,所以如果是大范围数据的批量处理,那么建议还是不要使用函数处理为好,可见在使用函数时一定要注意函数的上述特点,不能随意使用否则无法达到我们期望的效果。

  下面通过两个应用实例来说明如何通过函数实现局部范围扫描,以及使用函数实现局部范围扫描的应用场合。

  实例1:在前面说明如何利用嵌套视图实现局部范围扫描时,我们通过标量子查询实现了对分组操作的局部范围扫描,但是我们也说明了标量子查询并不是每个版本都提供支持,其实还以通过采用函数的方式来实现局部范围扫描。具体实现方式与步骤如下所示:

  (1)编写一个函数实现分组统计:

Create or replace function Get_avg_Stock(v_start in date,
                                  v_end in date,
                                  v_product_cd in varchar2)
return  number is
ret_val  number(10);
begin
select sum(stock_qty)/(v_end-v_start) into ret_val
from prod_stock
where product_cd=v_product_cd
and stock_date between v_start and v_end;
return ret_val;
end Get_avg_Stock;

  (2)使用函数编写SQL语句实现原有功能:

Select product_cd,product_name,
Get_avg_Stock(to_date(‘2010-01-01’,’yyyy-mm-dd’),
to_date(‘2010-12-31’,’yyyy-mm-dd’),
product_cd)
          from product
          where category_cd=’20’;

  通过上两个步骤,实现了将原来操作中的全部范围扫描的包装,并使得整个语句实现了局部范围扫描。

  实例二:在进行具有1:M关系的两张表的连接操作时,连接的结果会是M的集合,如果连接的目的是为了实现让M方的表针对从1方的表读出的中间结果进行校验,那么此时就会发生耗时全部范围数据扫描操作,因为为了将连接后的“M”集合简化为原来的“1”集合,需要进行额外的group by、distinct等操作,这大大增加了执行代价,因此尽量不要进行这种性质的连接操作。但当出现这种情况的需求时,可以通过实现函数来实现数据局部范围扫描,提升查询性能。见如下语句:

Select y.cust_no,y.cust_name,x.bill_tot
From (select a.cust_no,sum(b.bill_amt) bill_tot
     From account a,charge b
     Where a.acct_no=b.acct_no
     And a.bill_cd=’FEE’ and b.bill_ym between ‘2010’ and ‘2011’
     Grouo by a.cust_no
     Having sum(b.bill_amt)>5000000) x,customer y
Where y.cust_no=x.cust_no and y.cust_type=’IC’ and rownum<=30;

  该语句实现查询在2010年到2011年间,贸易总额在500万以上并且已经付款完成交易的前30位大客户信息。该语句执行过程中,优化器会制定首先执行内部的分组统计子查询,获得查询结果后再将结果与customer表进行连接,最后返回前30为大客户信息。在将子查询与customer表进行关联时,在连接条件y.cust_no=x.cust_no上其实进行的是用交易信息过滤客户信息,而客户信息与交易信息是1:M的关系,因此此时带来了额外的group by、distinct等引发全局范围扫描的操作,致使执行过程中处理了大量不必要的数据,导致执行性能低下。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号