Session重疊問題學習(八)--該問題第六次優化和Oracle版本
已經說好不玩了.還是不能罷手.
之前極致優化的方法,是先計算最小區間,再計算最小區間上的使用者數量.
其實可以一邊計算最小區間,同時計算最小區間上的使用者數量.
到了這個MySQL的版本,確實已經非常的晦澀難懂了.
由於MySQL沒有提供開窗函式,這種複雜計算非常的吃虧.
這個最後的版本,執行時間在 889毫秒到921毫秒之間.
MySQL 版本 最後還能優化小100毫秒,非常的不容易.
這個版本過於晦澀,我用同樣的思路,寫了一個Oracle版本的.
效能好,可讀性還強.
不像MySQL,需要考慮所有的細節.這個同樣演算法的Oracle版本,隨隨便便就能跑到213毫秒.
之前極致優化的方法,是先計算最小區間,再計算最小區間上的使用者數量.
其實可以一邊計算最小區間,同時計算最小區間上的使用者數量.
- DELIMITER $$
- CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()
- BEGIN
- drop table if exists t1;
- drop table if exists tmp_time_point;
- 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 tmp_time_point(
- roomid bigint,
- timepoint timestamp,
- type smallint,
- key(roomid,timepoint)
- ) engine=memory;
- create temporary table tmp_s(
- roomid bigint,
- userid bigint,
- s timestamp,
- e timestamp,
- i int
- ) engine=memory;
- SET @A=0;
- SET @B=0;
- insert into tmp_s
- SELECT x.roomid,x.userid,s,e,datediff(e,s)+1 i
- FROM
- (
- (
- SELECT @B:=@B+1 AS id,roomid,userid,s
- 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)
- ) AS p
- ) AS x,
- (
- SELECT @A:=@A+1 AS id,roomid,userid,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)
- ) AS o
- ) AS y
- )
- WHERE x.id = y.id AND x.roomid = y.roomid AND x.userid = y.userid ;
- 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 day),s) s,
- if(date(s+interval id-1 day)=date(e) ,e,date_format(s+interval id-1 day,'%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;
- select roomid,date(s) dt,round(sum(timestampdiff(second,date_format(s,'%Y-%m-%d %H:%i:%s'),date_format(e,'%Y-%m-%d %H:%i:%s')))/60) ts,max(rn) c from (
- select
- if(@roomid=roomid,@d,'') as s,@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') e ,rn
- from
- (
- select round(case when @roomid=roomid then @rn:=@rn+prevType when @roomid:=roomid then @rn:=prevType end) rn,b.prevType,roomid,timepoint,type from (
- select if(@roomid=roomid,@type,0) prevType ,case when @roomid=roomid then @type:=type when @roomid:=roomid then @type:=1 end,a.roomid,timepoint,type from (
- select * from ( select roomid,timepoint,sum(type) type from tmp_time_point group by roomid,timepoint) tmp_time_point,(select @roomid:=-1,@rn:=0,@type:=0) vars order by roomid ,timepoint
- ) a
- ) b order by roomid ,timepoint
- )p,(select @d:='',@roomid:=-1) vars
- order by roomid,timepoint
- ) v4 where s!='' and date(s)=date(e) and rn>=2
- group by roomid,date(s);
- END
到了這個MySQL的版本,確實已經非常的晦澀難懂了.
由於MySQL沒有提供開窗函式,這種複雜計算非常的吃虧.
這個最後的版本,執行時間在 889毫秒到921毫秒之間.
MySQL 版本 最後還能優化小100毫秒,非常的不容易.
這個版本過於晦澀,我用同樣的思路,寫了一個Oracle版本的.
效能好,可讀性還強.
- with c1 as -- 合併同一房間同一使用者的重疊時間段,用於統計峰值人數
- (
- select distinct roomid,userid,min(s) s,max(e) e
- from (select roomid,userid,s,e,
- sum(broken) over (partition by roomid, userid order by s,e) flag
- from (select t.*,
- (case when s <= max(e) over (partition by roomid, userid order by s,e rows between unbounded preceding and 1 preceding) then 0
- else 1
- end) as broken
- from (select roomid,userid,roomstart s,roomend e from u_room_log ) t
- ) t
- ) t
- group by roomid,userid,flag
- ),
- c2 as -- 拆分跨天的時間段
- (
- select *
- from (select roomid,userid,s,e
- from c1
- where trunc(s) = trunc(e) -- 不跨天
- union all
- select roomid,userid,
- case when id = 1 then s else trunc(s)+id-1 end s,
- case when id = m2 then e else (trunc(s)+id) -(1/24/60/60) end e
- from (select roomid,userid,s,e,id,
- max(id) over (partition by roomid,userid,s) m2
- from c1,nums
- where trunc(s) <> trunc(e) -- 跨天
- and id <= trunc(e)-trunc(s)+1) t1) t1
- ),
- c3 as -- 在計算最小範圍的同時,計算區間使用者數
- (
- select roomid,ts endtime,sum(prevType) over(partition by roomid order by ts) rn,
- lag(ts) over (partition by roomid order by ts) starttime
- from (
- select a.*,nvl(lag(type) over (partition by roomid order by ts),0) prevType
- from (
- select
- roomid,ts,sum(type) type
- from (
- select roomid,e ts, -1 type
- from c2
- union all
- select roomid,s ts, 1 type
- from c2
- ) group by roomid,ts
- ) a
- ) c
- )
- select roomid,to_char(dt,'yyyy-mm-dd HH24:mi:ss') dt,round(sum(dur)/60) ts,max(rn) c from (
- select roomid,trunc(starttime) dt,(endtime-starttime)*3600*24 dur,rn
- from c3 where rn>=2 and trunc(endtime)=trunc(starttime) and starttime is not null
- order by roomid,endtime
- )
- group by roomid,dt
- order by roomid,dt;
不像MySQL,需要考慮所有的細節.這個同樣演算法的Oracle版本,隨隨便便就能跑到213毫秒.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-2150464/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Session重疊問題學習(三)--優化Session優化
- Session重疊問題學習(五)--最優化Session優化
- Session重疊問題學習(四)--再優化Session優化
- Session重疊問題學習(六)--極致優化Session優化
- Session重疊問題學習(一)Session
- Session重疊問題學習(九)--該問題第七次優化.優化合並演算法Session優化演算法
- Session重疊問題學習(七)--小花狸合併演算法和最後一次優化Session演算法優化
- webpack dll打包重複問題優化Web優化
- 6.7 版本 Cookie 跟 Session 存入問題CookieSession
- oracle AS重啟問題Oracle
- Oracle效能優化視訊學習筆記-資料庫配置和I/O問題Oracle優化筆記資料庫
- SQL優化--not in和or出的問題SQL優化
- 【調優】設計問題還是優化問題?優化
- 學習Oracle Objects的文件和問題記錄OracleObject
- oracle效能問題:sql語句優化OracleSQL優化
- 凸優化問題優化
- 效能優化問題優化
- Struts Tiles 和 session的問題Session
- 解決問題oracle學習篇Oracle
- Oracle kill session相關問題(上)OracleSession
- Oracle kill session相關問題(下)OracleSession
- session共享問題???Session
- 【Oracle】Oracle wrong result一則(優化器問題)Oracle優化
- 優化Oracle with全表掃描的問題優化Oracle
- Shiro效能優化:解決Session頻繁讀寫問題優化Session
- react 學習 問題React
- 關於Oracle10g JOB執行是否會重疊的問題Oracle
- 八皇后問題分析和實現
- session的存取問題Session
- ORACLE常用傻瓜問題1000問(之八)(轉)Oracle
- ORACLE常用傻瓜問題1000問(之八) (轉)Oracle
- 優化Oracle with全表掃描的問題(二)優化Oracle
- 多版本oracle 軟體的問題Oracle
- Oracle Haip無法啟動問題學習OracleAI
- session跟蹤失效的問題和原因Session
- 03-凸優化問題優化
- Oracle中的Session kill不釋放問題OracleSession
- powershell 版本問題