zoukankan      html  css  js  c++  java
  • 一个 提高SQL 查询的讨论帖

    idn(关键字),产品名称,产品数量...
    B表,有字段:idn,a_idn(记录A表的关键字),工序,工时...
    A表与B表是一对多的关系,
    我想取到A表的明细及B表相关的总工时
    sele aa.* from a aa left outer join 
      (select a_idn,sum(工时) from b group by a_idn) bb on aa.idn=bb.a_idn
    这样虽然取得到我要的结果,可是速度很慢,尤其是我还有其它的表需要这样连接,一层套一层,导致速度奇慢无比,二千多条数据,要七八分钟才得到结果.这样肯定不行.
    请问应该怎么写才能提高查询速度?急盼高手提点


    不应该啊,我觉得1s内就应该搞定,就这么一个查询,没有别的么。
    还有你说的两千多条是之A表,还是B表?


    语句并不复杂,不应该市语句的问题


    A表加了条件才二千多条数据,今天客户打电话来说,查询时提示超时链接,我用SQL调试发现
    就是这个问题,左链接套了六层,一层比一层慢,最后就超时了!


    当然套一层左链接,慢是慢点,但还能出来,但是套多了就会链接超时!!!有没有改善办法?
    实在没法子只好用循环了,惨~~~~~~


    你用视图试试


    你的业务逻辑很复杂么,应该不至于7,8分钟的,不行的话,你就建临时表吧,把中间结果放进去。


    ......如果只是单纯的表与表链接速度很快,可是与GROUP by的统计结果再左链接速度就明显慢,我试试把统计做成用视图后再链接会不会快


    我的表不复杂,就是主表的[客户,加工类型,项目名称]都记的是代码,要中文信息,得在另三个对照表里取,还有要两个统计结果:到货数和加工工时,分别汇算自另外两个表.
    所以左链接套了六层...


    视图是不会提高效率的,它只是为了控制权限,或是查询格式。


    不要使用LEFT OUTER JOIN
    效率很低
    你这样写吧
    sele aa.* from a aa,  
      (select a_idn,sum(工时) from b group by a_idn) bb where aa.idn=bb.a_idn


    sele aa.* from a aa,  
      (select a_idn,sum(工时) from b group by a_idn) bb where aa.idn=bb.a_idn
    这样写有一个问题,不能把A表全部的数据显示出来呀


    能不能用存储过程呢?


    有这么夸张吗?感觉SQL语句不复杂,我更复杂的都写过,都用上游标了也没有这么慢啊。要不LZ用临时表试一下,临时表记录B表的总工时,这样可能会好一点把


    这种情况有一个通用的解决办法:根据情况你建立一个或者多个临时表,因为每个临时表数据量都不多,所以不会出现数据库链接超时的情况,万一数据量比较大,执行时间比较久,你还可以用进度条标识进度.


    可以这样
    select a.产品名称,a.产品数量 sum(b.工时)
    from A表 a,B表 b
    where a.idn = b.a_idn
    group by a.产品名称,a.产品数量


    是不复杂,可能是左链接套得太多,尤其和GROUP by的子查询进行左链接,会影响查询速度.
    临时表我一直没敢用,
    SELECT * INTO #tmp FROM 表,
    如果网络个多个用户同时查询,执得这条语句会不会冲突啊?临时表会自动删掉吧?


    不会冲突的,会话结束就删除了。


    临时表是微软都建议尽量避免使用,用了肯定慢
    优化一下索引试试
    用查询分析器的执行计划看看慢在哪儿


    我试过了,普通表左链速度很快,就是和GROUP by的子查询进行左链接,会影响查询速度,
    看来没有什么好办法了,我还是做循环得了~~~~~


    sele aa.*,b.a_idn,b.sum(工时) from a aa left join b group by a_idn on  aa.idn=bb.a_idn


    循环会快?group by 是会慢要按索引扫描表然后求和;b表的记录数有多少


    b表35824条数据,group by 后35677条,.........

    sele aa.*,b.a_idn,b.sum(工时) from a aa left join b group by a_idn on  aa.idn=bb.a_idn
    我试试,再问一下left join 和left outer join是不是一样的


    sele aa.*,b.a_idn,b.sum(工时) from a aa left join b group by a_idn on  aa.idn=bb.a_idn
    按这个格式试过一次了,提示"在关键字 'group' 附近有语法错误。",不行啊


    楼主是不是只有b表的数据3w条,那么你可以试试先让a与b的关联的结果插入到临时表,再用临时表进行下面的4个关联,那样应该可以快一些。


    如果在select里用子查询呢?比如:
    sele aa.*,(select sum(工时) from b where aa.idn=b.a_idn) as 工时
    from a aa 
    (可能更慢!)
    凡是有子查询的,一般都慢!


    A表37316条记录,取多少数据,视条件而定,或多或少不一定的.
    与B表类同的还有C表,有近6万条数据....
    本来一个SQL语句就能搞定的,现在弄得烦死人了!


    如果是sqlserver2000
    那么可以用
    declare @temp table(a varchar(10),b int)
    insert into @temp select a,b from ab where a='a'
    这样的临时表优化嵌套查询


    如果在select里用子查询呢?比如:
    sele aa.*,(select sum(工时) from b where aa.idn=b.a_idn) as 工时
    from a aa 
    (可能更慢!)
    凡是有子查询的,一般都慢!
    --------------------------
    我试了一下,3万条数据蛮快的,而且一条不少,真是非常感谢你!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


    谢谢各位的帮忙!非常感谢!yeskert1的答案解决了我大问题,不然要重写代码了!


    那楼主把你原来嵌套的group by 都去掉呢,你那样的写法&子查询应该没有差别啊,无非是少了个group by。


    A表3万条,B表3万条,单纯的left outer join速度很快,就是用group by 速度明显下降,

    yeskert1的答案,我试的时候蛮快的,怎么结完贴回去再试,就慢下来了呢,不过比原来的超时,总算是快点了,至少不会超时了.


    哈,我发现一个奇怪的现象,用yeskert1的办法,加条件反而比不加条件时慢,

    按理说加了条件,才二千条数据,应该更快才对,真是奇怪


    用SQL查询分析器,不加条件,14秒就涮出结果了,加了条件,1分半钟已过,结果还没出来.
    泪奔~~~~~~~~~~~~~~~~~~~`


    你把完整语句贴出来看看


    >>加条件反而比不加条件时慢,
    这是可能的,因为条件必然有比对的过程,字符串比较是耗时间的。group by a_idn导致慢也是这个原因。
    一般,这时应该为表增加索引来改善速度。

    能把完整语句贴出来吗?


    SELECT *
    FROM (SELECT c.*, isnull(d .wcsl, 0) AS wcsl
            FROM (SELECT a.*, isnull(a.sl * b.zgs, 0) AS zgs
                    FROM (SELECT a.*, isnull(b.xzlx, ' ') AS xzlx_sm
                            FROM (SELECT c.*, isnull(d .qym, ' ') AS qym
                                    FROM (SELECT a.*, isnull(b.xmm, ' ') AS xmm
                                            FROM ww_wwjl a LEFT OUTER JOIN
                                                  xmk b ON a.xm_dir = b.dir) c LEFT OUTER JOIN
                                          ww_khdak d ON c.khdm = d .khdm) a LEFT OUTER JOIN
                                  ww_xzlx b ON a.xzlx = b.xzlx_path) a LEFT OUTER JOIN
                              (SELECT wwjl_idn, SUM(gs) AS zgs
                             FROM ww_wwjl_gs
                             WHERE (sbname <> '@#$%')
                             GROUP BY wwjl_idn) b ON a.idn = b.wwjl_idn) c LEFT OUTER JOIN
                      (SELECT wwjl_idn, SUM(dhsl) AS wcsl
                     FROM ww_wwdh
                     WHERE dhrq >= '2006-01-01' AND dhrq <= '2006-12-31'
                     GROUP BY wwjl_idn) d ON c.idn = d .wwjl_idn) DERIVEDTBL
    WHERE (cj = '机械四课') AND (wwrq >= '2006-01-01') AND (wwrq <= '2006-12-31')
    ORDER BY xm_dir, th


    ------------------
    一共六个表:
    ww_wwjl是主表,与以下五个表左连接
    |---->xmk  (ww_wwjl.xm_dir=xmk.dir)
    |---->ww_khdak (ww_wwjl.khdm=xmk.khdm)
    |---->ww_xzlx (ww_wwjl.xzlx=xmk.xzlx_path)
    |---->ww_wwjl_gs (SUM(gs) group by wwjl_idn | ww_wwjl.idn=ww_wwjl_gs.wwjl_idn )
    |---->ww_wwdh  (SUM(dhsl) group by wwjl_idn | ww_wwjl.idn=ww_wwjl_gs.wwjl_idn )

    不知道有没有讲清楚~~~~


    头大了!太复杂了![:(]


    -_-|||,不管了,循环循环


    select a.*,b.... 
    from ww_wwjl a left join xmk b on a.xm_dir = b.dir
                   left join ww_khdak c on a.khdm = c.khdm
                   left join ww_xzlx d on a.xzlx = d.xzlx_path
                   left join (SELECT wwjl_idn, SUM(gs) AS zgs 
                              FROM ww_wwjl_gs WHERE (sbname <> '@#$%') 
                              GROUP BY wwjl_idn) e ON a.idn = e.wwjl_idn
           left join (SELECT wwjl_idn, SUM(dhsl) AS wcsl
                              FROM ww_wwdh
                              WHERE dhrq >= '2006-01-01' AND dhrq <= '2006-12-31'
                              GROUP BY wwjl_idn) f ON a.idn = f.wwjl_idn
    WHERE (cj = '机械四课') AND (wwrq >= '2006-01-01') AND (wwrq <= '2006-12-31')
    ORDER BY xm_dir, th


    doud2006谢谢,不过如果符合条件的记录数多的话,还是很慢很慢


    你的关联字段都是索引字段吗,不用的字段尽量不写,少出现*;结果对吗,没有重复关联吧


    不是啊,我没有用索引,我没有用过索引,只有ww_wwjl的idn是关键字
    记录数是对的,没有重复的关联


    没索引是全表扫描,当然慢,6个表关联字段都加索引试试;如果这几个表不是很频繁更新不包括insert; where 条件也尽可能用索引;


    请问,加了索引,会不会影响我其它的查询语句呀??????


    呀,下班了,我明天来试.谢谢


    索引会提高查询效率,在数据发生变化时需要更新索引,会降低更新效率


    我对索引不是很明白,在网上找了资料看看了,还有很多不懂的地方.
    请问unique values打上勾是不是就是群集索引了?

    在非群集索引下,数据在物理上随机存放在数据页上,在范围查找时,必须执行一次表扫描才能找到这一范围内的全部行。

    在群集索引下,数据在物理上按顺序在数据页上,重复值也排列在一起,因而在范围查找时,可以先找到这个范围的起末点,且只在这个范围内扫描数据页,避免了大范围扫描,提高了查询速度。

    那么非群集索引与没用索引不是没区别了吗?象我要汇算总工时,group by,就需要用群集索引了是不是?


    你可以查一下sqlserver2000的帮助CREATE INDEX;解释的很清楚了


    我试过了,我对需要GROUP  by 的字段进行了聚集索引,速度快了好多哦!不知道会不会对其它操作有影响!我还要测试一下.不过,我先得向你道谢.可是我已经结贴了,不知道还有没有其它办法给你加分呀doud2006


    不过我有一个问题,我现在只有一个字段group by ,如果我还有别的字段也需要GROUP by的话,但聚集索引只能做一次,那么是不是只能将建立索引放在程序里啊?这样频繁得删除建立聚集索引可取吗?

  • 相关阅读:
    通用权限管理设计 之 数据库结构设计
    jQuery LigerUI 插件介绍及使用之ligerDateEditor
    jQuery LigerUI 插件介绍及使用之ligerTree
    jQuery LigerUI V1.01(包括API和全部源码) 发布
    jQuery liger ui ligerGrid 打造通用的分页排序查询表格(提供下载)
    jQuery LigerUI V1.1.5 (包括API和全部源码) 发布
    jQuery LigerUI 使用教程表格篇(1)
    jQuery LigerUI V1.0(包括API和全部源码) 发布
    jQuery LigerUI V1.1.0 (包括API和全部源码) 发布
    nginx keepalived
  • 原文地址:https://www.cnblogs.com/cy163/p/1313079.html
Copyright © 2011-2022 走看看