select sum(BALANCELY)
  from t_fact_loan_m t
 where inputdate = '2012/01'
   and t.duebillno in
       (select distinct t1.duebillno
          from t_fact_loan_m t1
         where t1.customertype in ('0301', '0103')
            or t1.duebillno in
               (select distinct t2.duebillno
                  from t_fact_loan_m t2
                  join ent_info e on t2.customerid = e.customerid
                 where e.scope2 in ('4', '5')));运行的太慢了!求优化sql优化

解决方案 »

  1.   

    不能格式化一下么?
    or t1.duebillno in 这句用得着in么?连接不行么?
    or能不能改union
    你为啥那么喜欢in呢?
      

  2.   

    你不觉得与其把时间放在SQL优化上,在逻辑上,或者在service层上优化一下更合适么
      

  3.   

    in 改成    exists 事实看看。
     然后用sql 工具看看执行计划到底哪一步比较慢。也有可能是建表问题。
      

  4.   

    尽量用JOIN,JOIN用不了再考虑exist,能不用IN尽量不用IN,当然,还得根据实际情况
      

  5.   

    1、最大可能优化SQL语句,不要欺负数据库:SELECT SUM(balancely)
    FROM t_fact_loan_m t1 LEFT JOIN ent_info e ON t2.customerid = e.customerid
    WHERE inputdate = '2012/01' AND ( 
            t1.customertype IN ('0301', '0103') OR e.scope2 IN ('4', '5'))
          )2、执行语句分析,得到数据库执行计划,利用索引等手段,设法消除全表扫描;
      

  6.   

    吧表 字段 这个sql的业务逻辑搞出来啊
      

  7.   


    楼主测试过我 6 楼优化后的SQL么?
      

  8.   

    仔细一看原来LZ把简单sql写复杂了,估计LZ看到ldh911的回复后,就直接一口血喷屏幕上。
      

  9.   

    早上刷牙突然想起这sql,改得不对。
    select sum(BALANCELY)
      from t_fact_loan_m t
     where inputdate = '2012/01'
       and t.duebillno in
           (select distinct t2.duebillno
              from t_fact_loan_m t2
              join ent_info e
                on t2.customerid = e.customerid
             where e.scope2 in ('4', '5')
                or t2.customertype in ('0301', '0103'));

    select sum(BALANCELY)
      from (select distinct t2.duebillno
              from t_fact_loan_m t2
              join ent_info e
                on t2.customerid = e.customerid
             where e.scope2 in ('4', '5')
                or t2.customertype in ('0301', '0103')) a
      left join t_fact_loan_m t
        on t.duebillno = a.duebillno
     where inputdate = '2012/01';
      

  10.   

    早上刷牙突然想起这sql,改得不对。
    select sum(BALANCELY)
      from t_fact_loan_m t
     where inputdate = '2012/01'
       and t.duebillno in
           (select distinct t2.duebillno
              from t_fact_loan_m t2
              join ent_info e
                on t2.customerid = e.customerid
             where e.scope2 in ('4', '5')
                or t2.customertype in ('0301', '0103'));

    select sum(BALANCELY)
      from (select distinct t2.duebillno
              from t_fact_loan_m t2
              join ent_info e
                on t2.customerid = e.customerid
             where e.scope2 in ('4', '5')
                or t2.customertype in ('0301', '0103')) a
      left join t_fact_loan_m t
        on t.duebillno = a.duebillno
     where inputdate = '2012/01';帮我去看看我发的那个帖子啊
      

  11.   


    这个子查询:
           (select distinct t1.duebillno
              from t_fact_loan_m t1
             where t1.customertype in ('0301', '0103')
                or t1.duebillno in
                   (select distinct t2.duebillno
                      from t_fact_loan_m t2
                      join ent_info e on t2.customerid = e.customerid
                     where e.scope2 in ('4', '5')))合并成一个的时候,不用外连接是不行的,因为 t2.customerid = e.customerid 可能会有匹配不上的情况。而楼主原语句的意思里面,只要 t1.customertype in ('0301', '0103') 成立,后面的“or t1.duebillno in”子查询就不重要了,所以即便连接不上也没关系。
    楼主原查询中所有的 distinct 其实都没意义,既然都用in了,消除同名除了消耗时间并没有任何帮助。
      

  12.   


    这个子查询:
           (select distinct t1.duebillno
              from t_fact_loan_m t1
             where t1.customertype in ('0301', '0103')
                or t1.duebillno in
                   (select distinct t2.duebillno
                      from t_fact_loan_m t2
                      join ent_info e on t2.customerid = e.customerid
                     where e.scope2 in ('4', '5')))合并成一个的时候,不用外连接是不行的,因为 t2.customerid = e.customerid 可能会有匹配不上的情况。而楼主原语句的意思里面,只要 t1.customertype in ('0301', '0103') 成立,后面的“or t1.duebillno in”子查询就不重要了,所以即便连接不上也没关系。
    楼主原查询中所有的 distinct 其实都没意义,既然都用in了,消除同名除了消耗时间并没有任何帮助。
    我把join当成left join了,写错了一点。
    T_FACT_LOAN_M表
    INPUTDATE DUEBILLNO CUSTOMERID CUSTOMERTYPE BALANCELY
    2012/01 6 1
    2012/01 1 1
    2012/01 4 44 0103 1
    2012/01 3 33 0103 1
    2012/01 2 22 0301 1
    2012/01 1 11 0301 1ent_info表
    CUSTOMERID SCOPE2
    11 4
    33 5
    楼主sql结果5,你给的sql结果4,我提供的这两个sql结果才和楼主一样。
    select sum(BALANCELY)
      from t_fact_loan_m t
     where inputdate = '2012/01'
       and t.duebillno in
           (select t2.duebillno
              from t_fact_loan_m t2
              left join ent_info e
                on t2.customerid = e.customerid
             where e.scope2 in ('4', '5')
                or t2.customertype in ('0301', '0103'));select sum(BALANCELY)
      from (select t2.duebillno
              from t_fact_loan_m t2
              left join ent_info e
                on t2.customerid = e.customerid
             where e.scope2 in ('4', '5')
                or t2.customertype in ('0301', '0103')) a
      left join t_fact_loan_m t
        on t.duebillno = a.duebillno
     where inputdate = '2012/01';
    我感觉自己好蛋疼,这种问题同事问我,我估计我都不懒的回答,论坛上的讨论我竟然去验证下。
    装B和争胜负才是人性的原罪啊。
      

  13.   


    晚上想研究下哪里考虑步骤,但是
    你贴出来的数据是不是漏了啥?我用我的SQL 和 楼主的SQL测试了结果都是4啊【俺的】SELECT sum(balancely)
    FROM t_fact_loan_m t LEFT JOIN ent_info e ON t.customerid = e.customerid
    WHERE inputdate = '2012/01' AND ( 
                t.customertype IN ('0301', '0103') OR e.scope2 IN ('4', '5')
          );   
    【楼主的】select sum(BALANCELY)
      from t_fact_loan_m t
     where inputdate = '2012/01'
       and t.duebillno in
           (select distinct t1.duebillno
              from t_fact_loan_m t1
             where t1.customertype in ('0301', '0103')
                or t1.duebillno in
                   (select distinct t2.duebillno
                      from t_fact_loan_m t2
                      join ent_info e on t2.customerid = e.customerid
                     where e.scope2 in ('4', '5')));
    我拿你14楼的语句也试了下,也是 4 。 
      

  14.   

    尴尬不是漏了,是位置造成误会了。
    T_FACT_LOAN_M表
    INPUTDATE DUEBILLNO CUSTOMERID CUSTOMERTYPE BALANCELY
     2012/01 6 null null 1
     2012/01 1 null null 1
     2012/01 4 44   0103 1
     2012/01 3 33   0103 1
     2012/01 2 22   0301 1
     2012/01 1 11   0301 1
    直接复制没注意null是看不到的
      

  15.   


    试验了下你的数据,你说的没错。从优化的SQL来说,我觉得你给出的第一种是比较不错的。不过老实说,再看了下楼主的SQL,我有点觉得楼主自己源SQL写得可能点漏洞(又或者是这个举例的数据有点过头了),作为“贷款表”,没有“用户ID”,这个记录在业务语义上来说应该是无效的。。Anyway...