畫像預先計算的一點設想.時間段分片

壹頁書發表於2018-11-16

畫像最佳化告一段落。

ES在分群階段的效果非常好.但是在增量指標計算時 ES顯得非常吃力。


什麼是增量指標計算呢?比如使用者的點選次數,消費情況,這個原來在一個Hive表儲存.

每個使用者每天一條記錄.

那麼如果一個群分了50萬人,統計他們9月1日至11月1日的消費情況.則需要掃描 50w*62  三千一百萬記錄


這個資料量太大,所以增量指標計算的速度非常慢.


因為是離線資料,可以用空間換取時間。

我先給每週打一個標識.以2018年1月1日為基準,每增加一週,week id 自增 1.

這樣以後所有的周都有了連續的自增ID。


2018年1月1日基準周開始,以每四周為維度統計一次,然後再以每兩週為維度統計一次,最後在以每週為維度統計一次。


除了以若干周為維度,還可以更加細化。每週 星期一至星期三,星期四至星期五,週六至週日,再增加三個細分的維度。


那麼 50w使用者 從9月1日至11月1日的統計, 


set @startDate:='20180901';
set @endDate:='20181101';
select * from (
	select  
	concat('week',weekCount,'-',startWeek) flag
	,startWeek,startDate,endDate,7*weekCount days,weekCount
	from (
		select 
		case when days =14 then w4id else w2id end  startWeek,
		min(startDate) startDate,max(endDate) endDate,sum(days) days,floor(sum(days)/7) weekCount
		from (
			select w2id,max(w4id) w4id,min(startDate) startDate,max(endDate) endDate,sum(days) days from (
				select  
				wid,
				floor(wid/2)*2 w2id,floor(wid/4)*4 w4id,
				count(*) days, 
				min(dt) startDate, 
				max(dt) endDate 
				from ( 
					select 
					id,dt,
					floor(datediff(str_to_date(startDate,'%Y%m%d') + interval id-1 day,'2018-01-01')/7) as wid
					from (
						select 
						id, 
						str_to_date(@startDate,'%Y%m%d') + interval id-1 day  dt,
						@startDate startDate,
						@endDate endDate
						from nums where id<= 
						datediff(str_to_date(@endDate,'%Y%m%d'),str_to_date(@startDate,'%Y%m%d'))+1 
					) t1 
				) t2 group by wid  having count(*)=7
			) t3 group by w2id
		) t4 group by case when days =14 then w4id else w2id end 
	) t5 
	union 
	select if(days=1,'single day',flag) flag,wid,startDate,endDate,days,weekCount from (
		select   flag,min(wid) wid,min(startDate) startDate,max(endDate) endDate,count(*) days,0 weekCount
		from (
			select 
			wid,
			startDate+ interval (id-1) day startDate,
			startDate+ interval (id-1) day endDate,
			case 
			when
			 weekday(startDate+ interval (id-1) day)+1 in(1,2,3) then 'day-1-3'
			when
			 weekday(startDate+ interval (id-1) day)+1 in(4,5) then 'day-4-5'
			when
			 weekday(startDate+ interval (id-1) day)+1 in(6,7) then 'day-6-7'
			end flag
			from (
				select  
				wid,
				floor(wid/2)*2 w2id,floor(wid/4)*4 w4id,
				count(*) days, 
				min(dt) startDate, 
				max(dt) endDate 
				from ( 
					select 
					id,dt,
					floor(datediff(str_to_date(startDate,'%Y%m%d') + interval id-1 day,'2018-01-01')/7) as wid
					from (
						select 
						id, 
						str_to_date(@startDate,'%Y%m%d') + interval id-1 day  dt,
						@startDate startDate,
						@endDate endDate
						from nums where id<= 
						datediff(str_to_date(@endDate,'%Y%m%d'),str_to_date(@startDate,'%Y%m%d'))+1 
					) t1 
				) t2 group by wid  having count(*)!=7
			) t3 ,nums where nums.id<=days
		) t4 group by flag
	) t5 
) r order by startDate;





flag表示 聚合維度. 可以是 4周聚合維度,2周聚合維度,單週聚合維度,星期1,2,3維度,星期4,5維度,星期6,7維度和單天

startWeek表示維度開始時間所在的周ID

startDate表示開始日期

endDate表示結束日期

days表示維度內天數

weekCount表示維度包含的星期數


如果按照不同粗細維度預先計算.則原來需要掃描4 三千一百萬 記錄可以縮小為

50w*7 (上述範圍可以拆分為7個時段)  三百五十萬記錄

掃描量僅為原來的 11%


代價是儲存的增加.按照上述維度,儲存空間會膨脹到原來的1.68倍。





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-2220384/,如需轉載,請註明出處,否則將追究法律責任。

相關文章