加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

Session重叠难题学习

发布时间:2022-03-25 15:51:57 所属栏目:编程 来源:互联网
导读:这是对这个问题的算法总结和最后一次优化. 经过这次优化,在我的电脑上(SSD硬盘,机械硬盘还是没有这么快),运行时间是980毫秒左右.真正意义上的秒出.并且我确实觉得是优无可优了。 之所以能从10秒的版本,跳跃优化到1.6s,1.3s的版本.是因为采用了小花狸Session
      这是对这个问题的算法总结和最后一次优化.
     经过这次优化,在我的电脑上(SSD硬盘,机械硬盘还是没有这么快),运行时间是980毫秒左右.真正意义上的秒出.并且我确实觉得是优无可优了。
 
     之所以能从10秒的版本,跳跃优化到1.6s,1.3s的版本.是因为采用了小花狸Session合并算法。
 
     但是该规律仅仅存在于用户首尾时间段不重合的情况.
     比如A用户上线时间是 10点至11点整,而用户B上线时间是11点整到12点.
     因为11点整这个时刻,用户A和B重合了,所以这个算法就不能生效了.
 Session重叠难题学习
所以当时取巧,如果重合了,就增加或者减去一个很小的时间
s+interval startnum/1000000 second s,      
e-interval endnum/1000000 second e
 
insert into t2 (roomid,s,e)      
select roomid,      
s+interval startnum/1000000 second s,      
e-interval endnum/1000000 second e      
 from (      
    select       
    roomid,      
    s,e,      
    startnum,      
    when @eflag=eflag then @rn:=@rn+1 when @eflag:=eflag then @rn else @rn end endnum      
    from (      
        select * from (      
            select when @sflag=sflag then @rn:=@rn+1 when @sflag:=sflag then @rn else @rn end startnum,roomid,s,e,sflag,eflag from      
            (      
                select * from       
                (      
                    select t1.*,concat('[',roomid,'],',s) sflag,concat('[',roomid,'],',e) eflag from t1 order by roomid ,sflag      
                )a,(select @sflag:='',@rn:=0,@eflag:='') vars      
            ) b        
        ) bb order by roomid,eflag      
    ) c      
) d ;  
 
但是这样引入一个问题,就是有误差.误差只能缩小却不能消除.
这也是为什么1.3s和1.6s版本使用timestamp(6)的原因,就是为了缩小误差.
 
改进的过程如下:
 
DELIMITER $$  
  
CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()  
BEGIN        
    drop table if exists t1;        
    drop table if exists t2;      
    drop table if exists tmp_time_point;        
    drop table if exists tmp_min_range;      
    drop table if exists tmp_s;    
    CREATE temporary TABLE `t1` (        
      `roomid` int(11) NOT NULL DEFAULT '0',        
      `userid` bigint(20) NOT NULL DEFAULT '0',        
      `s` timestamp,        
      `e` timestamp,    
       primary key(roomid,userid,s,e)    
    ) ENGINE=memory;        
      
   CREATE temporary TABLE `t2` (        
      `roomid` int(11) NOT NULL DEFAULT '0',        
      `timepoint` timestamp,        
        c int,  
        key(roomid,timepoint)  
    ) ENGINE=memory;        
 
select max(i) into @c from tmp_s;    
        
insert ignore into t1(roomid,userid,s,e)      
select           
roomid,  userid,          
if(date(s)!=date(e) and id>1,date(s+interval id-1 date(s+interval id-1 date(e) ,e,date_format(s+interval id-1 '%Y-%m-%d 23:59:59')) e          
from tmp_s t1 STRAIGHT_JOIN        
nums on(nums.id<=t1.i)    
where nums.id<=@c    
       
;          
      
    -- 开始点+1,结束点-1  
    insert into tmp_time_point(roomid,timepoint,type) select roomid,s,1 from t1;      
    insert into tmp_time_point(roomid,timepoint,type) select roomid,e,-1 from t1;   
  
    -- 计算每个点的标号  
    insert into t2(roomid,timepoint,c)   
    select roomid,timepoint,from tmp_time_point group by  roomid,timepoint;  
  
    -- 计算最小范围  
    insert ignore into tmp_min_range(roomid,s,e)      
                select   roomid,starttime  starttime, endtime  endtime from (        
                    select         
                    if(@roomid=roomid,@d,'')  as starttime,@d:=str_to_date(timepoint,'%Y-%m-%d %H:%i:%s.%f'),@roomid:=roomid,p.roomid,str_to_date(timepoint,'%Y-%m-%d %H:%i:%s.%f') endtime        
                    from tmp_time_point p,(select @d:='',@roomid:=-1) vars        
                    order by roomid,timepoint        
                ) v4 where starttime!='' and date(starttime)=date(endtime);      
         
  
    select roomid,date(s) dt,round(second,date_format(s,'%Y-%m-%d %H:%i:%s'),date_format(e,'%Y-%m-%d %H:%i:%s')))/60) ts,max(num) c from   
    (  
        select a.roomid,num,a.s,a.e from (  
            select when @roomid=roomid and date(@timepoint)=date(timepoint) then @num:=@num+prevC when @roomid:=roomid then @num:=0 end num,@timepoint:=timepoint ,a.* from (  
                select when @roomid=roomid then @prevC  when @roomid:=roomid then @prevC:=0 end prevC,@prevC:=c,b.* from (  
                    select * from t2 ,(select @roomid:=-1,@timepoint:='',@num:=0,@prevC:=-1) vars  
                ) b order by roomid,timepoint  
            ) a order by roomid,timepoint  
        ) c   
        inner join       
                tmp_min_range a on( c.timepoint=a.e and c.roomid=a.roomid)    
        where num>=2  
    ) d  group by roomid,date(s);   &nb

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读