需求:在个储存过程里有多个select多表联合查询,共同点是都联合到同一个表,我能不能做类似如下的优化(ps:这储存过程要被循环八百多万次,不优化不行):注意那个变量v_array
select acct_type into v_array from bonus_acct_type where is_use = '0';  select nvl(sum(a.xxx), 0)
    into v_test_1
    from 表1 a
   where a.state = '00A'
     and a.cust_id = 1102061249
     and a.acct_type in (v_array);  select nvl(sum(a.xxx), 0)
    into v_test_2
    from 表2 a
   where a.state = '00A'
     and a.cust_id = 1102061249
     and a.acct_type in (v_array);……不知道我描述得清楚不。

解决方案 »

  1.   


    我是楼主,我的意思说,下面这条语句,会返回多行结果,我怎么把这多行结果赋给变量,再把这变量作为in参数:
    select acct_type into v_array from bonus_acct_type where is_use = '0';
      

  2.   

    type v_array is table of varchar2;
      

  3.   

    你闲的慌么
      select nvl(sum(a.xxx), 0)
        into v_test_1
        from 表1 a
       where a.state = '00A'
         and a.cust_id = 1102061249
         and a.acct_type in (select acct_type from bonus_acct_type where is_use = '0';
    );
      

  4.   

    你实际是想把 select acct_type from bonus_acct_type where is_use = '0' 的结果保存一下,这样让其他表与此关联时,不需要再从 bonus_acct_type 里搜索(bonus_acct_type 表数据较多)是吗?如果是这个想法
    你建一个临时表
    将结果插入到临时表里,其他表关联时,从临时表关联,这样数据量小很多了
      

  5.   

    正如5楼所说,我是想避免多次查询bonus_acct_type,在真个储存过程里有8个对这表的查询,而且查询结果都是一样的,所以没必要查询那么多次。想把查询结果保存成变量后重复使用,期待解答。
      

  6.   

    但建立临时表始终会对磁盘做读写,多次反复查询也不如保存成内存变量性能快,毕竟有八个bonus_acct_type查询语句和至少八百万次的循环,这么说一共有6400000次的bonus_acct_type查询了
      

  7.   

    in 里面写变量,只有一种方法----动态sql
    要用动态sql就要循环数组进行拼接,你自己考虑。
      

  8.   

    如果你非要用变量的话
    那你可以创建一个  table of varchar2 的类型
    create or replace type type_name is table of varchar2(4000);
    把 select acct_type from bonus_acct_type where is_use = '0' 的结果保存到 type_name 这个对象里最后使用 and a.acct_type in (select column_value from table(type_name ))
      

  9.   

    你在统计的时候不能把这张 user 的大表也带着,一次性统计所有用户?
      

  10.   

    楼主就是想通过数组来处理么?参考 fetch bulk collect into 
    set serveroutput on;
    declare
    vs_t1 varchar2(10);
    l_last_num     number(4);
    type v_array is table of bonus_acct_type.acct_type%TYPE INDEX BY BINARY_INTEGER;
    g_array v_array;
    cursor cur_test is select acct_type from bonus_acct_type;
    begin
     open  cur_test;
     fetch cur_test bulk collect into g_array;
     l_last_num := g_array.last;
     dbms_output.put_line(to_char(l_last_num));
     
     for l_loop_cntr in 1..l_last_num loop
       select .. into vs_t1 from 表1 a where t1 in g_array(l_loop_cntr) and rownum = 1;
       dbms_output.put_line(g_array(l_loop_cntr));
     end loop;
     close cur_test;
    end;
      

  11.   

    你说的是嵌套表,不是数组。数组你这样用是会报错滴。 ORA-22095
      

  12.   

    即使对客户分组,每个组的数据量也不小,希望能加快运行速度。原来的储存过程跑了三天还没出结束怎么说也是六台小型机oracle集群,这效率也太低了
      

  13.   

    因为只用存储过程跑的话,再快也只能是单进程处理。
    不知道条件是否允许,用C或者JAVA分多线程调用存储过程。
    你可能会想:即使是多线程跑存储过程,操作的也是同一张表。。
    但是:可以在C或JAVA调用存储过程的时候,把线程号做为参数传到存储过程中,每个线程处理1-10000或者10000-20000号的数据。
    这样会加快速度。我们项目中有这样的例子。
      

  14.   

    我不知道。。
    opps_zhou和BenChiM888,谁回一下啊?
      

  15.   

    可以在系统没人查询的时候禁用索引,提高插入速度,等插入完成再重建索引。
    或者 采用多线程插入 百度一下:oracle parallel
      

  16.   

    http://www.examda.com/oracle/zhonghe/20071205/11175056.html
      

  17.   

    所谓800万次是对 cust_id = 1102061249 这个有800万个,其他逻辑都一样?
    那非常没必要每个ID对存储过程调用,应该合并到这里面来
    业务逻辑不能改,实现方式可以换下用临时表,如果必须800万次,可以看下在一个800万循环内,你打算放到数组中的数据是否都一样?一样的话可以用全局临时表或固化表,在第一次执行存储过程前初始化
      

  18.   

    cust_id = 1102061249是测试时临时加上去的,生产时应去掉这个。其实我就是想避免多次读取一张表的动作。