当前位置:编程学习 > JAVA >>

SQL语句优化

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 优化 --------------------编程问答-------------------- 不能格式化一下么?
or t1.duebillno in 这句用得着in么?连接不行么?
or能不能改union
你为啥那么喜欢in呢? --------------------编程问答-------------------- 你不觉得与其把时间放在SQL优化上,在逻辑上,或者在service层上优化一下更合适么 --------------------编程问答-------------------- in 改成    exists 事实看看。
 然后用sql 工具看看执行计划到底哪一步比较慢。也有可能是建表问题。 --------------------编程问答-------------------- 换成连接查询试一下 --------------------编程问答-------------------- 尽量用JOIN,JOIN用不了再考虑exist,能不用IN尽量不用IN,当然,还得根据实际情况 --------------------编程问答-------------------- 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、执行语句分析,得到数据库执行计划,利用索引等手段,设法消除全表扫描; --------------------编程问答-------------------- 用执行计划看下  是否全盘扫描 --------------------编程问答-------------------- 吧表 字段 这个sql的业务逻辑搞出来啊。。。 --------------------编程问答--------------------
引用 楼主 Dolls_Man 的回复:
运行的太慢了!求优化


楼主测试过我 6 楼优化后的SQL么? --------------------编程问答-------------------- 仔细一看原来LZ把简单sql写复杂了,估计LZ看到ldh911的回复后,就直接一口血喷屏幕上。 --------------------编程问答--------------------
引用 6 楼 ldh911 的回复:
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、执行语句分析,得到数据库执行计划,利用索引等手段,设法消除全表扫描;

早上刷牙突然想起这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 楼 zxcvbnm11920 的回复:
Quote: 引用 6 楼 ldh911 的回复:

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'))
      )
很牛x的样子哦


2、执行语句分析,得到数据库执行计划,利用索引等手段,设法消除全表扫描;

早上刷牙突然想起这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 楼 zxcvbnm11920 的回复:
早上刷牙突然想起这sql,改得不对。


这个子查询:
       (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了,消除同名除了消耗时间并没有任何帮助。 --------------------编程问答--------------------
引用 13 楼 ldh911 的回复:
Quote: 引用 11 楼 zxcvbnm11920 的回复:

早上刷牙突然想起这sql,改得不对。


这个子查询:
       (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 1

ent_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和争胜负才是人性的原罪啊。 --------------------编程问答--------------------
引用 14 楼 zxcvbnm11920 的回复:
我感觉自己好蛋疼,这种问题同事问我,我估计我都不懒的回答,论坛上的讨论我竟然去验证下。
装B和争胜负才是人性的原罪啊。


晚上想研究下哪里考虑步骤,但是。。。
你贴出来的数据是不是漏了啥?我用我的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 。。。。  --------------------编程问答--------------------
引用 15 楼 ldh911 的回复:
晚上想研究下哪里考虑步骤,但是。。。
你贴出来的数据是不是漏了啥?我用我的SQL 和 楼主的SQL测试了结果都是4啊。。。
尴尬不是漏了,是位置造成误会了。
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是看不到的。。。 --------------------编程问答--------------------
引用 16 楼 zxcvbnm11920 的回复:
尴尬不是漏了,是位置造成误会了。
直接复制没注意null是看不到的。。。


试验了下你的数据,你说的没错。

从优化的SQL来说,我觉得你给出的第一种是比较不错的。

不过老实说,再看了下楼主的SQL,我有点觉得楼主自己源SQL写得可能点漏洞(又或者是这个举例的数据有点过头了),作为“贷款表”,没有“用户ID”,这个记录在业务语义上来说应该是无效的。。。。。Anyway...
补充:Java ,  Java EE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,