- 大數據SQL優化:原理與實踐
- 陳鶴 楊國棟
- 1925字
- 2025-02-10 16:29:10
1.3 大數據SQL的弊端
SQL作為聲明式語言降低了接入成本,大大增強了開發靈活性。但凡事有利弊,大數據引擎屏蔽了大量細節的描繪,大量優化和物理實現過程對用戶不透明,當SQL執行性能有欠缺或者遇到瓶頸時,調優或者排查問題的過程和時間就會大幅增加。
1.3.1 易學難精
不同的SQL盡管描述的是相同的結果,但是在其底層實現、查詢優化以及數據結構等因素的影響下,實際的執行開銷可能會有很大差異,這非常考驗開發人員的技術功底以及對各框架的了解程度。比如同樣是統計每種交易類型的訂單量和金額,消耗同樣的資源,使用不同的寫法,產生的時間開銷就會不一樣。


語句1只是簡單地對訂單類型聚合后進行求和計數,而語句2運用了兩階段聚合的優化手段,雖然后者在寫法上不便理解,但執行時長能減少50%左右。我們只有對執行的引擎有一定了解,才能在查詢或執行遇到瓶頸時,得心應手地進行優化。
1.3.2 表達能力有限
SQL中缺乏一些必要的數據類型和運算定義,這使得某些高性能算法無法描述,只能寄希望于計算引擎在工程層面的優化。傳統關系型數據庫經過幾十年的發展,優化經驗已經相當豐富,但即便如此仍有許多場景難以被優化,理論層面的問題確實很難在工程層面解決。而大數據生態在優化方面的經驗還遠遠不如傳統數據庫,算法上不占優勢,就只能靠增加計算節點的數量來提高性能。
另外,SQL描述過程的能力不太好,不擅長指定執行路徑,想獲得高性能往往需要專門優化的執行路徑,這又需要增加許多特殊的修飾符來人為干預,但這種做法不如直接使用過程性語言來得直接。此外,在復雜計算方面,SQL實現得很煩瑣。例如統計所有直播間用戶的觀看時間,SQL的計算邏輯大致為,利用每5s發送一次的心跳事件來追蹤用戶的觀看時長,這些心跳事件會應用在用戶進入直播間、觀看直播期間,并且沒有將應用置于后臺或退出時上報。查詢任務如下所示。



為了滿足上述要求這里采用了相當復雜的方法,以至于代碼編寫起來困難重重,僅是理解其中的邏輯,就要耗費大量時間。此外,利用SQL來執行過程性計算也非常困難。所謂過程性計算,就是那些不能一氣呵成的計算過程,它們需要分多個步驟來完成,尤其是那些涉及數據順序的復雜運算。例如統計一周內累計登錄時長超過1h的用戶占比,但要剔除登錄時長小于10s的誤操作情況;統計信用卡在最近3個月內最長連續消費的天數分布情況,考慮實施連續消費10天后積分3倍的促銷活動;統計1個月中有多少用戶在24h內連續進行了查看商品操作后加入購物車并購買的動作,有多少用戶在中間步驟放棄購買。為了實現這類過程性運算,僅憑SQL去編寫相應的邏輯往往難度較大,通常還需輔以UDF才能實現。如果連SQL代碼都難以構建,那么SQL的使用效果將大打折扣。
1.3.3 與關系型數據庫求同存異
大數據SQL在站在關系型數據庫“巨人肩膀”上的同時,也存在著以下的差異或“弊端”。在大數據生態中,SQL語句不僅代表查詢語句,也用來表達計算的過程。在關系型數據庫中,MySQL的查詢引擎和存儲是緊耦合的,這其實是有助于優化性能的,不能把它們拆分開來。而大數據SQL的引擎一般都獨立于數據存儲系統之外,更為靈活一些。
在大數據生態中,SQL語句不僅可以表達靜態數據集上的查詢,還可以表示流計算的計算過程,也就是兼容離線數據分析和實時數據分析。流計算(流式SQL)是一種將傳統的SQL查詢語法與流式計算框架(如Apache Flink、Apache Kafka Streams、Apache Beam等)結合起來的方法,通過使用流式SQL,可以通過SQL的簡潔和表達力來定義實時數據流的轉換和處理邏輯。
大多數大數據引擎不支持索引和事務。大數據引擎面對的數據規模通常非常大,存儲在分布式文件系統或分布式數據庫中。傳統的索引技術在大數據的情況下可能無法擴展,并且索引的維護和更新成本很高。大數據場景下的查詢通常需要更加靈活和復雜,需要支持復雜的數據處理和分析操作。傳統的索引技術可能無法滿足這些需求,因為索引通常適用于簡單的點查詢或范圍查詢,而對于復雜的聚合、連接和多維分析等操作則效果有限。
在SQL開發或優化過程中,必須考慮具體的物理實現。在大數據生態中,大部分任務都基于“分而治之”的原則解決,也就是通過大內存、集群化和并行處理來實現。例如在SQL中,JOIN操作是基于鍵值對進行匹配的,但在大內存環境下,可以直接通過內存地址進行匹配,無須進行哈希計算和比對,這樣可以顯著提高性能。
SQL的數據表是無序的,單表計算可以較容易地實現分段切片并行處理。然而在進行多表關聯運算時,通常需要預先設定固定的數據分段,難以實現動態數據分段。這同時也限制了SQL根據機器負載,動態決定并行處理數量的能力。在集群計算方面,SQL理論上不區分維度表和事實表,JOIN操作被簡單地定義為笛卡兒積的生成與過濾。大規模表的JOIN操作不可避免地會引發占用大量網絡資源的Shuffle操作。當集群節點過多時,網絡傳輸引起的延遲可能會抵消增加節點帶來的性能優勢。