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

Session重叠难题学习 --再优化

发布时间:2022-03-30 16:15:44 所属栏目:MySql教程 来源:互联网
导读:接前文: 需求描述和第一版解决方案(执行时间90秒) 优化和修改bug的版本(执行时间25秒) 我觉得在集合思维处理方式中,前文已经达到最优了. 如果放弃完全的集合处理思维,实际上还可以更加的优化. 前文的几个问题. 1.引入了过多的表结构. 2.写表本身也花费了时
       接前文:
      需求描述和第一版解决方案(执行时间90秒)
 
     优化和修改bug的版本(执行时间25秒)
 
     我觉得在集合思维处理方式中,前文已经达到最优了.
 
     如果放弃完全的集合处理思维,实际上还可以更加的优化.
 
前文的几个问题.
1.引入了过多的表结构.
2.写表本身也花费了时间.
3.前文按天批处理,粒度还是细了.应该一把批量全出最快.
4.前文计算最小间隔范围的部分,因为应用集合化思维,不好理解性能还差.
 
前文计算最小间隔范围的部分如下
select roomid,as DATETIME) starttime,as DATETIME) endtime from (    
     select @d as starttime,@d:=d,v3.roomid,v3.d endtime from (    
                select distinct roomid,     
                when nums.id=1 then v1s       
                when nums.id=2 then v1e       
                when nums.id=3 then v2s       
                when nums.id=4 then v2e       
                end d   from (    
                    select   v1.roomid, v1.s v1s,v1.e v1e,v2.s v2s,v2.e v2e    
                    from t1 v1    
                    inner join t1 v2 on ((v1.s between v2.s and v2.e or v1.e between v2.s and v2.e )  and v1.roomid=v2.roomid)     
                    where v2.roomid in(select distinct roomid from t1 where date(s)=pTime)    
                    and v2.s>=pTime and v2.s<(pTime+interval '1' and (v2.roomid,v2.userid,v2.s,v2.e)!= (v1.roomid,v1.userid,v1.s,v1.e)     
                ) a,nums where nums.id<=4    
                order by roomid,d    
    ) v3,(select @d:='') vars    
) v4 where starttime!=''
 
该部分使用集合处理方式,不好理解性能还差.
 
这块可以通过游标写临时表轻易解决。
本质上最小范围就是
每天每个房间每个记录的开始时间和结束时间都扣出来作为一行 排序。
 
然后找到每个时间最近的下一个时间,作为最小时间范围.
 
如果使用游标,遍历一遍即可.
 
DELIMITER $$  
  
CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()  
BEGIN  
    declare done int default 0;      
    declare v_roomid bigint;  
    declare v_start timestamp;  
    declare v_end timestamp;  
    declare cur_test CURSOR for select roomid,s,e from t1  ;  
  
    DECLARE  CONTINUE HANDLER FOR NOT FOUND  SET done = 1;      
      
    drop table if exists t1;  
    drop table if exists tmp_time_point;  
    CREATE temporary TABLE `t1` (  
      `roomid` int(11) NOT NULL DEFAULT '0',  
      `userid` bigint(20) NOT NULL DEFAULT '0',  
      `s` timestamp NOT NULL DEFAULT ON UPDATE timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
      primary KEY `roomid` (`roomid`,`s`,`e`,`userid`)  
    ) ENGINE=InnoDB;  
  
    create temporary table tmp_time_point(  
            roomid bigint,  
            timepoint timestamp,  
            primary key(roomid,timepoint)  
    ) engine=memory;  
  
  
insert into t1  
select distinct    
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 (    
SELECT DISTINCT s.roomid, s.userid, s.s, (      
        SELECT MIN(e)      
        FROM (SELECT DISTINCT roomid, userid, roomend AS e      
            FROM u_room_log a      
            WHERE NOT EXISTS (SELECT *      
                FROM u_room_log b      
                WHERE a.roomid = b.roomid      
                    AND a.userid = b.userid      
                    AND a.roomend >= b.roomstart      
                    AND a.roomend < b.roomend)      
            ) s2      
        WHERE s2.e > s.s      
            AND s.roomid = s2.roomid      
            AND s.userid = s2.userid      
        ) AS e      
FROM (SELECT DISTINCT roomid, userid, roomstart AS s      
    FROM u_room_log a      
    WHERE NOT EXISTS (SELECT *      
        FROM u_room_log b      
        WHERE a.roomid = b.roomid      
            AND a.userid = b.userid      
            AND a.roomstart > b.roomstart      
            AND a.roomstart <= b.roomend)      
    ) s, (SELECT DISTINCT roomid, userid, roomend AS e      
    FROM u_room_log a      
    WHERE NOT EXISTS (SELECT *      
        FROM u_room_log b      
        WHERE a.roomid = b.roomid      
            AND a.userid = b.userid      
            AND a.roomend >= b.roomstart      
            AND a.roomend < b.roomend)      
    ) e      
WHERE s.roomid = e.roomid      
    AND s.userid = e.userid     
    
) t1 ,    
nums     
where  nums.id<=datediff(e,s)+1    
;    
  
    open cur_test;      
    repeat      
        fetch cur_test into v_roomid, v_start,v_end;      
        if done !=1 then    
           insert ignore into tmp_time_point(roomid,timepoint) values(v_roomid,v_start);  
           insert ignore into tmp_time_point(roomid,timepoint) values(v_roomid,v_end);  
        end if;    
    until done end repeat;      
    close cur_test;   
       
select roomid,date(s) dt,round(second,s,e))/60) ts,max(c) c from (       
    select roomid,s,e ,distinct userid) c  from (  
        select distinct v6.roomid,v6.userid,greatest(s,starttime) s,least(e,endtime) e  
        from (  
            select distinct roomid,as DATETIME) starttime,as DATETIME) endtime from (  
                select   
                if(@roomid=roomid,@d,'')  as starttime,@d:=timepoint,@roomid:=roomid,p.roomid,p.timepoint endtime  
                from tmp_time_point p,(select @d:='',@roomid:=-1) vars  
                order by roomid,timepoint  
            ) v4 where starttime!='' and date(starttime)=date(endtime)  
        ) v5 inner join t1 v6 on(v5.starttime between v6.s and v6.e and v5.endtime between v6.s and v6.e and v5.roomid=v6.roomid)  
    ) v6 group by roomid,s,e having distinct userid)>1     
) v7 group by roomid,date(s);  
  
  
END  
 
都内聚到一个过程之后,不需要创建额外的普通表,直接在过程中创建临时表.实现高内聚,低耦合.
 
call p
过程返回的结果即为最终结果.
 
三次测试耗时均低于 10.3秒

(编辑:温州站长网)

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

    热点阅读