Session重疊問題學習(四)--再優化
接前文:
需求描述和第一版解決方案(執行時間90秒)
http://blog.itpub.net/29254281/viewspace-2150229/
優化和修改bug的版本(執行時間25秒)
http://blog.itpub.net/29254281/viewspace-2150259/
我覺得在集合思維處理方式中,前文已經達到最優了.
如果放棄完全的集合處理思維,實際上還可以更加的優化.
前文的幾個問題.
1.引入了過多的表結構.
2.寫表本身也花費了時間.
3.前文按天批處理,粒度還是細了.應該一把批量全出最快.
4.前文計算最小間隔範圍的部分,因為應用集合化思維,不好理解效能還差.
前文計算最小間隔範圍的部分如下
該部分使用集合處理方式,不好理解效能還差.
這塊可以通過遊標寫臨時表輕易解決。
本質上最小範圍就是
每天每個房間每個記錄的開始時間和結束時間都扣出來作為一行 排序。
然後找到每個時間最近的下一個時間,作為最小時間範圍.
如果使用遊標,遍歷一遍即可.
都內聚到一個過程之後,不需要建立額外的普通表,直接在過程中建立臨時表.實現高內聚,低耦合.
call p
過程返回的結果即為最終結果.
三次測試耗時均低於 10.3秒
需求描述和第一版解決方案(執行時間90秒)
http://blog.itpub.net/29254281/viewspace-2150229/
優化和修改bug的版本(執行時間25秒)
http://blog.itpub.net/29254281/viewspace-2150259/
我覺得在集合思維處理方式中,前文已經達到最優了.
如果放棄完全的集合處理思維,實際上還可以更加的優化.
前文的幾個問題.
1.引入了過多的表結構.
2.寫表本身也花費了時間.
3.前文按天批處理,粒度還是細了.應該一把批量全出最快.
4.前文計算最小間隔範圍的部分,因為應用集合化思維,不好理解效能還差.
前文計算最小間隔範圍的部分如下
- select roomid,CAST(starttime as DATETIME) starttime,CAST(endtime as DATETIME) endtime from (
- select @d as starttime,@d:=d,v3.roomid,v3.d endtime from (
- select distinct roomid,
- case
- 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' day) 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 CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- `e` 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 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 (
- 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(sum(timestampdiff(second,s,e))/60) ts,max(c) c from (
- select roomid,s,e ,count(distinct userid) c from (
- select distinct v6.roomid,v6.userid,greatest(s,starttime) s,least(e,endtime) e
- from (
- select distinct roomid,CAST(starttime as DATETIME) starttime,CAST(endtime 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 count(distinct userid)>1
- ) v7 group by roomid,date(s);
- END
都內聚到一個過程之後,不需要建立額外的普通表,直接在過程中建立臨時表.實現高內聚,低耦合.
call p
過程返回的結果即為最終結果.
三次測試耗時均低於 10.3秒
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-2150297/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL優化學習手札(四) 單表訪問方法MySql優化
- webpack dll打包重複問題優化Web優化
- Shiro效能優化:解決Session頻繁讀寫問題優化Session
- 【機器學習】--迴歸問題的數值優化機器學習優化
- Laravel 第四張學習——優化頁面(1)Laravel優化
- 再探強化學習強化學習
- session共享問題???Session
- 凸優化問題優化
- 又出 bug 了 ?Safari 下文字和省略號重疊問題
- Laravel 第四章學習——優化頁面(2)Laravel優化
- 強化學習-學習筆記11 | 解決高估問題強化學習筆記
- Android 百度地圖InfoWindow 出現重疊的問題Android地圖
- 2020年了,別再重複學習原型了原型
- 斜率優化(凸包優化)DP問題acm優化ACM
- hibernate中的no session問題Session
- (譯)別再使用 JWT 作為 Session 系統!問題重重且很危險。JWTSession
- 03-凸優化問題優化
- 數值最優化—優化問題的解(二)優化
- Fragment重影(重疊)白屏等問題原理解析,以及解決方案Fragment
- react 學習 問題React
- 禁用 COOKIE 後如何訪問 SESSION 問題CookieSession
- SceneKit-解決模型重疊時渲染畫面閃爍的問題模型
- 再談優雅重試(retry)機制
- go的編譯優化問題Go編譯優化
- 【離散優化】覆蓋問題優化
- 記一個效能優化問題優化
- N皇后問題(各種優化)優化
- Silverlight 2 學習筆記之事件的重複繫結問題筆記事件
- mysql left join 優化學習MySql優化
- MySQL優化學習手札(三)MySql優化
- 斜率優化學習筆記優化筆記
- Tarjan再學習
- 學習方向的問題
- Spark學習——問題排查Spark
- 面經問題學習
- 《java學習三》jvm效能優化-------調優JavaJVM優化
- iOS8 自定義UITabBar (使用popToViewController導致的UITabBarButton重疊的問題)iOSUItabBarViewController
- Oracle效能優化-SQL優化(案例四)Oracle優化SQL
- 決策樹減支問題(優化)dfs減支問題優化