Hive_SQL_複雜SQL_計算最大在線人數

原文鏈接: 

1.Hive SQL複雜場景實現(2) —— 實時/最大在線人數

https://blog.csdn.net/adrian_wang/article/details/89840671

 

背景

   之前遇到這個問題:,能不能用SQL求某一天哪個時刻進行中的訂單量最多,這個數是多少?我尋思挺有意思,就細想了一下。其實思考下可以發現,如果要求一段時間內的同時處於服務過程中的最大訂單量,相當於也要知道每個時刻的數量,所以求最大和求實時是等同的。

   這個問題在不同的業務場景下有不同的意義,比如一個遊戲的同時在線人數,比如一個服務器的實時併發數,比如一個倉庫的貨物積壓數量等等。

   一般而言對於需要知道併發數的業務場景都會通過實時監控來完成,而不會通過sql進行離線計算。但本着深挖sql潛能的想法,如下提供一個不切實際的解法與一個真實可行的方法。

數據

  假設我們的業務場景是回溯某一天的某遊戲的最大同時在線人數,並有表connection_detail記錄用戶每一次上線和下線時間:

user_id    login_time   logout_time     dt
213142  2019-01-01 12:21:22  2019-01-01 13:45:21  20190101
412321   2019-01-01 13:35:11  2019-01-01 16:01:49  20190101
…    …    …    …

 
        

解法

  大致思路 窗口函數 sum() over()

   我們先拋開sql,來考慮實時計算中我們怎麼處理該問題。是不是我們會實時記錄着一個變量online_cnt,當一個用戶登錄時加1,用戶下線時減1?

   再假如我讓你用python離線處理這個問題你會怎麼做。應該先把登錄時間和登出時間這兩列打散成行,然後進行排序,最後一行行讀入,當讀到一個登錄時間時online_cnt加1,讀到登出時間時online_cnt減1。

   回到sql,我們來嘗試用SQL實現上述邏輯。我們給登錄時間加一個數值標記1,登出時間加標記-1。然後對排序後的數據求和該字段,最終得到我們的結果。

select
    max(max_index)
from 
(
    select
        sum(index) over(order by `timestamp`) as max_index --排序後第一行到本行的和
    from
    (
        select
            order_id,
            unix_timestamp(login_time) as `timestamp`,
            1 as index
        from
            connection_detail
        where
            dt = '20190101'
            and is_td_finish = 1
        union all
        select
            order_id,
            unix_timestamp(logout_time) as `timestamp`,
            -1 as index
        from
            connection_detail
        where
            dt = '20190101'
    )a  --將登錄時間和登出時間多列成多行
)b

  可能阻礙大家想到這一邏輯的點在於sum() over()這一用法,該窗口函數對每一行數據實現了計算第一行到該行的求和計算,具體介紹網上很多,不熟悉的同學可以百度一下。該代碼對於千萬量級的數據sparksql計算了65秒,屬於一個可以接受的範圍。

  理解了上述代碼的同學可以發現過程中我們一度得到了每個時刻的在線人數(子查詢b)。對這一數據進行可視化可以直觀瞭解服務器的負載變化情況。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章