首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 性能问题:请高手为我排忧解难,在线恭候大驾光临 [已结帖,结帖人:zhougang86]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-08-19 10:08:52 楼主
    CREATE procedure QueryACCP @StartTime datetime,@EndTime datetime
    as
    declare @STCD char(8)
    declare @ACCP float
    create table #Result(STCD CHAR(8) ,ACCP float)
    declare STCDCursor cursor
    for
    select distinct STCD from ViewHourQuery where TM between @StartTime and @EndTime

    open STCDCursor
    while(0=0)
    begin
    fetch next from STCDCursor into @STCD
    if(@@FETCH_STATUS <>0) BREAK
    set @ACCP=dbo.TotalACCP(@STCD,@StartTime,@EndTime)
    insert into #Result values(@STCD,@ACCP)
    end
    close STCDCursor
    deallocate STCDCursor
    select a.STCD,a.STNM,b.ADDVNM,c.ACCP from (ST_STBPRP_B a left outer join ST_ADDVCD_B B on a.ADDVCD=b.ADDVCD)inner join #Result c on a.STCD=c.STCD
    drop table #Result

    这是我写的存储过程,查询一段时间以内的各个站点的降雨量,STCD是站点号,ACCP是降雨量,最后连接2张表,投影STNM(站点名称),ADDVNM(站点所属城市名称)
    TotalACCP函数是计算一个STCD的降雨量,里面用到了其他的几个函数
    因为表中的记录不是连续的,有的没有进行统计,如某一天的记录没有,则调用NotExistDay求
    NotExist1stXun(上旬记录没有)、NotExist2stXun(中旬记录没有)、NotExist3stXun(下旬记录没有)、NotExistMonth(月记录没有),计算的过程是:如果时间段跨月,则先在月表里去记录,该月记录不存在,则调用NotExistMonth求之,再在剩余的时间段里,够得上旬的则在旬表里取(旬分上、中、下),不够的则调用相应的函数求,再按同样的思路在天表里,最后在到时段表(给时间分段,取值再合计)
    1.create function NotExistDay(@STCD CHAR(8),@Time datetime)---统计日降雨量函数
    returns float
    as
    begin
    declare @number float
    set @number=0
    select @number=isnull(sum(DRP),0)from ViewHourQuery where STCD=@STCD and TM between dateadd(dd,datediff(dd,0,@Time),0)and dateadd(ms,-3,dateadd(dd,datediff(dd,0,@Time),0))
    return @number
    end

    其他的几个函数就不贴上来了,时段表记录有36万条,日表记录有18万条....
    我现在是能求出相应站点在一个时间段内的降雨量了,但是性能太差了,360个站点要耗4分钟17秒,聚集索引也建立了,看看我的存储过程,能不能不写游标,游标很耗时间,我在执行计划里看了下,占34%(80多秒了),希望您能帮帮我!
    100  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wufeng4552
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 10:09:271楼 得分:0
    help you up
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • 184270428
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 10:54:252楼 得分:0
    去掉cursor,看看会好一些不?
    CREATE procedure QueryACCP @StartTime datetime,@EndTime datetime
    as
    declare @STCD char(8)
    declare @ACCP float
    declare @Result table (STCD CHAR(8) primary key,ACCP float)
    insert @Result
    select distinct
    STCD,accp_new = dbo.TotalACCP(STCD,@StartTime,@EndTime)
    from ViewHourQuery(index=idx_vq_tm)--这个你要建好
    where
    TM between @StartTime and @EndTime


    select a.STCD,a.STNM,b.ADDVNM,c.ACCP from
    (ST_STBPRP_B a left outer join ST_ADDVCD_B B on a.ADDVCD=b.ADDVCD)
    inner join @Result c on a.STCD=c.STCD
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 10:55:513楼 得分:0
    怎么没有人帮帮我啊
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sdxiong
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:06:084楼 得分:0
    才几十万的记录,取数为什么还要分日、旬、月呢,做一大堆的判断还不如把所有数再统计一次,楼主是把简单问题复杂化了

    SQL code
    select b.stcd,b.stnm,c.addvnm,sum(a.drp) from viewhourquery a left join st_stbprp_b b on a.stcd=b.stcd left join st_addvcd_b c on b.addvcd=c.addvcd where a.tm >= dateadd(dd,datediff(dd,0,@Time),0) and a.tm < dateadd(dd,datediff(dd,0,@Time)+1,0) group by b.stcd,b.stnm,c.addvnm

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:07:375楼 得分:0
    回复:184270428
    我也试过了去掉游标,执行后好象比原来有游标的还要慢很多
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:10:346楼 得分:0
    回复:sdxiong

    我开始时也试过,的确是可以,而且才几秒钟,可是项目经理要我按任务要求做啊,我这个是学习任务!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • 184270428
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:10:467楼 得分:0
    再试试这样:

    CREATE procedure QueryACCP @StartTime datetime,@EndTime datetime
    as
    declare @STCD char(8)
    declare @ACCP float
    declare @Result table (STCD CHAR(8) primary key,ACCP float)
    insert @Result
    select
    STCD,accp_new = isnull(sum(DRP),0)
    from ViewHourQuery(index=idx_vq_tm)--这个你要建好 再建pk_stcd_tm比较一下用(index=pk_stcd_tm)
    where
    TM between @StartTime and @EndTime
    group by
    stcd

    select a.STCD,a.STNM,b.ADDVNM,c.ACCP from
    ST_STBPRP_B a(index=pk_ST_STBPRP_B_stcd)--如果可以,把stcd建成ST_STBPRP_B主键或聚集索引
    inner join @Result c(index=pk_stcd_tm) on a.STCD=c.STCD
    left outer join ST_ADDVCD_B B
    on a.ADDVCD=b.ADDVCD
                     


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sdxiong
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:22:478楼 得分:0
    引用 6 楼 zhougang86 的回复:
    回复:sdxiong

    我开始时也试过,的确是可以,而且才几秒钟,可是项目经理要我按任务要求做啊,我这个是学习任务!



    无语了,有快的方法不用,偏要用慢的。。。。

    按你现在这样的写法,如果是有几千万的数据,不知要算多久了,恐怕到时泪水比算出来的雨水要多了,呵呵
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:23:079楼 得分:0
    回复:184270428
    这样不合任务的要求,没有分段取值,与本意相差甚远
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:28:1210楼 得分:0
    引用 8 楼 sdxiong 的回复:

    无语了,有快的方法不用,偏要用慢的。。。。

    按你现在这样的写法,如果是有几千万的数据,不知要算多久了,恐怕到时泪水比算出来的雨水要多了,呵呵


    呵呵,是的啊,不过经理说他们以前写了一个功能一样的,500个站点只花17秒时间,我现在功能是实现了,现在优化就是我的目标,以前在学校里学的都是SQL入门,现在需求不一样了啊,我还得慢慢想啊
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:28:3411楼 得分:0
    引用 8 楼 sdxiong 的回复:

    无语了,有快的方法不用,偏要用慢的。。。。

    按你现在这样的写法,如果是有几千万的数据,不知要算多久了,恐怕到时泪水比算出来的雨水要多了,呵呵


    呵呵,是的啊,不过经理说他们以前写了一个功能一样的,500个站点只花17秒时间,我现在功能是实现了,现在优化就是我的目标,以前在学校里学的都是SQL入门,现在需求不一样了啊,我还得慢慢想啊
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • flairsky
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:41:1412楼 得分:100
    这个架构是好的

    问题是游标+函数=遍历函数,问题大咯,你每做次统计,就是扫描一次某级别的表,360个站点,扫描表360次!

    我认为,你需要先判断,而不是判断一个做一次统计

    先判断每个站点在哪个级别能找到相应数据,然后同级别做一次统计,最后结果union all,这样你只要扫描(级别数)次表

    我说清楚了没?


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • flairsky
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:42:3313楼 得分:0
    这样时间大概为(4*60+17)/90

    10秒以内
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 11:57:1414楼 得分:0
    引用 12 楼 flairsky 的回复:
    这个架构是好的

    问题是游标+函数=遍历函数,问题大咯,你每做次统计,就是扫描一次某级别的表,360个站点,扫描表360次!

    我认为,你需要先判断,而不是判断一个做一次统计

    先判断每个站点在哪个级别能找到相应数据,然后同级别做一次统计,最后结果union all,这样你只要扫描(级别数)次表

    我说清楚了没?


    我知道了,我现在也在往这方面考虑,尽可能的减少读取表次数,可真不好判断啊,对一个时间段进行分段讨论:夸月就在月表记录里查,旬则在旬表记录里查(旬还分上、中、下),其他类似,麻烦的是我还得逐一判断这些记录存不存在,期望到最后最多是在月、旬、日、时段表里面各取一次记录。你给我提议很好,真是我所想的,我努力朝这个方向去做
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 12:00:1515楼 得分:0
    引用 13 楼 flairsky 的回复:
    这样时间大概为(4*60+17)/90

    10秒以内

    这个是怎么估算的,我看不懂
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • flairsky
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 12:00:5116楼 得分:0
    引用 14 楼 zhougang86 的回复:
    引用 12 楼 flairsky 的回复:
    这个架构是好的

    问题是游标+函数=遍历函数,问题大咯,你每做次统计,就是扫描一次某级别的表,360个站点,扫描表360次!

    我认为,你需要先判断,而不是判断一个做一次统计

    先判断每个站点在哪个级别能找到相应数据,然后同级别做一次统计,最后结果union all,这样你只要扫描(级别数)次表

    我说清楚了没?


    我知道了,我现在也在往这方面考虑,尽可能的减少读取表次数,可真不好判…


    你总要判断的,是不?
    归类后再查
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • flairsky
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-19 12:02:0917楼 得分:0
    引用 15 楼 zhougang86 的回复:
    引用 13 楼 flairsky 的回复:
    这样时间大概为(4*60+17)/90

    10秒以内

    这个是怎么估算的,我看不懂


    这个,你做完我再说
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-20 10:58:2718楼 得分:0
    引用 17 楼 flairsky 的回复:
    引用 15 楼 zhougang86 的回复:
    引用 13 楼 flairsky 的回复:
    这样时间大概为(4*60+17)/90

    10秒以内

    帅哥,帮我再看下,我现在的思路可有问题了:
    我先创建一个临时表table1(tablename char(16),querytime datetime)用来存储该从哪个表读取数据
    如:查询ACCP=‘50100100’的站点在2008-4-1 8:00:00 到2008-4-23 6:00:00的降雨量
    判断后得到临时表table1的数据是:
    tablename        querytime
    View1stXunQuery    2008.4    (上旬)
    view2stXunQuery    2008.4    (中旬)
    ViewDayQuery      2008-4-21
    ViewDayQuery      2008-4-22
    ViewDayQuery      2008-4-23
    ViewhourQuery      2008-4-23
    这样取数据的次数是少了,可是我每次还得判断记录存不存在(从表里扫描,要很多次)
    select @total=@total+isnull(sum(ACCP),0) from dbo.View1stXunQuery  a where STCD=@STCD and
    exists
    (select * from #QueryTable  b where b.Tablename='View1stXunQuery' and datepart(yy,b.QueryTime)=datepart(yy,a.IDTM) AND DATEPART(mm,b.QueryTime)=datepart(mm,a.IDTM)

    )

    最后再这样读数据(相关子查询),看看可有什么好的方法啊

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhougang86
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 09:34:1719楼 得分:0
    好了,现在搞定了,多亏了flairsky的帮助:
    批量过滤,过程如下:
    先找出在月表中有记录的站点
    select STCD,IDTM,ACCP into #Month from ViewMonthQuery where IDTM BETWEEN ** AND ** AND stcd IN
    (SELECT DISTINCT stcd from ViewHourQuery where TM between ** and **)

    再在上旬表记录塞选,在这个时间段有记录,并且月份不和表记录的月份相同
    select STCD,IDTM ,ACCP INTO #1stXun from View1stXunQuery  a where IDTM BETWEEN ** AND **
    AND stcd IN (SELECT DISTINCT stcd from ViewHourQuery where TM between ** and **)
    and not exists(select * from #Month b where a.STCD=b.STCD and datepart(yy,a.IDTM)=datepart(yy,b.IDTM)and datepart(mm,a.IDTM)=datepart(mm,b.IDTM))

    其他类似,最后分组求和 select STCD,SUM(ACCP)as ACCP from ** group by STCD
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved