爲什麼大數據平臺要回歸 SQL

先說觀點:因爲還沒找到更好的。

接下來說原因,首先來看看大數據平臺都在幹什麼。

原因

結構化數據計算仍是重中之重

大數據平臺主要是爲了應對海量數據存儲和分析的需求,海量數據存儲的確不假,除了生產經營產生的結構化數據,還有大量音視頻等非結構化數據,這部分數據很大,佔用的空間也很多,有時大數據平臺 80% 以上都存儲着非結構化數據。不過,數據光存儲還不行,只有利用起來才能產生價值,這就要進行分析了。

大數據分析要分結構化和非結構化數據兩部分討論。

結構化數據主要是企業生產經營過程中產生的業務數據,可以說是企業的核心,以往在沒有大數據平臺的時候企業主要或全部在使用的就是這部分數據。隨着業務的不斷積累,這部分數據也越來越大,傳統數據庫方案面臨很大挑戰,建設大數據平臺自然要解決這部分核心數據分析問題。

有了大數據平臺,給大家的想象空間也大了起來,以往無法利用的日誌、圖片、音視頻等非結構化數據也要產生價值,這就涉及到非結構化數據分析了。相對核心業務數據分析,非結構化數據分析看起來更像是錦上添花。即使如此,非結構化數據分析並不是孤立存在,也還會伴隨大量結構化數據處理。採集非結構化數據的同時,常常會伴隨着採集許多相關的結構化數據,比如音視頻的製作人、製作時間、所屬類別、時長、…;有些非結構化數據經過處理後也會轉變成結構化數據,比如網頁日誌中拆解出訪問人 IP、訪問時刻、關鍵搜索詞等。所謂的非結構化數據分析,經常實際上是針對這些伴生而出的結構化數據。

結構化數據分析仍然是大數據平臺的重中之重。而結構化數據處理技術就比較成熟了,比如我們常用的基於關係數據模型的關係數據庫(SQL)。

SQL 仍是目前最廣泛的結構化數據計算技術

迴歸 SQL 卻是當前大數據計算語法的一個發展傾向。在 Hadoop 體系中,早期的 PIG Latin 已經被淘汰,而 Hive 卻一直堅挺;Spark 上也在更多地使用 Spark SQL,而 Scala 反而少很多(Scala 易學難精,作爲編譯型語言不支持熱部署也有很多不方便之處)。其它一些新的大數據計算體系一般也將 SQL 作爲首選的計算語法,經過幾年時間的混戰,現在 SQL 又逐步拿回了主動權。

這個現象,大概有這麼兩個原因:

1. 實在沒什麼別的好用

關係數據庫過於普及,程序員對 SQL 相當熟悉,甚至思維習慣都是 SQL 式的。SQL 用來做一些常規查詢也比較簡單,雖然用於處理複雜的過程計算或有序運算並不方便,但其它那些替代技術也好不到哪裏去,碰到 SQL 難寫的運算一樣要寫和 UDF 相當的複雜代碼,反正都是麻煩,還不如繼續用 SQL。

2. 大數據廠商的鼎力支持

大數據的技術本質是高性能,而 SQL 是性能比拼的關鍵陣地。比性能要面對同樣的運算纔有意義,過於專門和複雜的運算涉及的影響因素太多,不容易評估出大數據平臺本身的能力。而 SQL 有國際標準的 TPC 系列,所有用戶都看得懂,這樣就有明確的可比性,廠商也會把性能優化的重點放在 SQL 上。

兼容 SQL 更利於移植

大數據平臺兼容 SQL 的好處是很明顯的,SQL 的應用非常廣泛,會 SQL 的程序員很多,如果繼續採用 SQL 則可以避免許多學習成本。支持 SQL 的前端軟件也很多,使用 SQL 的大數據平臺很容易融入這個現成的生態圈中。大數據平臺打算替代的傳統數據庫也是 SQL 語法的,這樣兼容性會很好,移植成本相對較低。

好了,我們說完大數據平臺爲什麼會迴歸關係數據模型了。那麼繼續使用關係數據模型(SQL)會存在哪些問題呢?

問題

性能低

繼續使用 SQL 的最大問題就是難以獲得大數據計算最需要的高性能。

SQL 中缺乏一些必要的數據類型和運算定義,這使得某些高性能算法無法描述,只能寄希望於計算引擎在工程上的優化。傳統商業數據庫經過幾十年的發展,優化經驗已經相當豐富,但即使這樣仍有許多場景難以被優化,理論層面的問題確實很難在工程層面解決。而新興的大數據平臺在優化方面的經驗還遠遠不如傳統數據庫,算法上不佔優,就只能靠集羣更多的機器獲得性能提升。另外,SQL 描述過程的能力不太好,不擅長指定執行路徑,而想獲得高性能常常需要專門優化的執行路徑,這又需要增加許多特殊的修飾符來人爲干預,那還不如直接用過程性語法更爲直接,這也會妨礙用 SQL 寫出高性能的代碼。

SQL 發明之初的計算機硬件能力還比較差,要保證實用性,SQL 的設計必須適應當時的硬件條件,這就導致了 SQL 很難充分利用當代計算機的硬件能力,具體來說就是大內存、並行和集羣。SQL 中的 JOIN 是按鍵值對應的,而大內存情況下其實可以直接用地址對應,不需要計算 HASH 值和比對,性能可以提高很多;SQL 的數據表無序,單表計算時還容易做到分段並行,多表關聯運算時一般就只能事先做好固定分段,很難做到同步動態分段,這就難以根據機器的負載臨時決定並行數量;對於集羣運算也是這樣,SQL 在理論上不區分維表和事實表,JOIN 運算簡單地定義爲笛卡爾積後過濾,要實現大表 JOIN 就會不可避免地產生佔用大量網絡資源的 HASH Shuffle 動作,在集羣節點數太多時,網絡傳輸造成的延遲會超過節點多帶來的好處。

舉個具體的例子,我們想在 1 億條數據中取出前 10 名,用 SQL 寫出來是這樣的:

select top 10 x,y from T order by x desc

這個語句中有個 order by,嚴格按它執行就會涉及大排序,而排序非常慢。其實我們可以想出一個不用大排序的算法,但用 SQL 卻無法描述,只能指望數據庫優化器了。對於這句 SQL 描述的簡單情況,很多商用數據庫確實都能優化,使用不必大排序的算法,性能通常很好。但情況複雜一些,比如在每個分組中取前 10 名,要用窗口函數和子查詢把 SQL 寫成這樣:

select * from
 (select y,*,row_number() over (partition by y order by x desc) rn from T)
where rn<=10

這時候,數據庫優化器就會犯暈了,猜不出這句 SQL 的目的,只能老老實實地執行排序的邏輯(這個語句中還是有 order by 的字樣),結果性能陡降。

開發效率低

不僅跑的慢,開發效率也不高,尤其在複雜計算方面,SQL 實現很繁瑣。比如根據股票記錄查詢某隻股票最長連續上漲天數,SQL(oracle)的寫法如下:

SELECT MAX(ContinuousDays)-1
    FROM (
        SELECT code, NoRisingDays, COUNT(*) ContinuousDays
        FROM (
            SELECT code,
            SUM(RisingFlag) OVER (PARTITION BY code ORDER BY day) NoRisingDays
            FROM (
                SELECT code, day,
                CASE WHEN price>
                    LAG(price) OVER (PARTITION BY code ORDER BY day)
                THEN 0 ELSE 1 END RisingFlag
                FROM stock
            )
        ) GROUP BY NoRisingDays
    )

用了很繞的方式實現,別說寫出來,看懂都要半天。

此外,SQL 也很難實現過程計算。什麼是過程性計算呢?就是一步寫不出來,需要多次分步運算,特別是與數據次序相關的運算。

我們舉幾個例子來看:

一週內累計登錄時長超過一小時的用戶佔比,但要除去登錄時長小於 10 秒的誤操作情況

信用卡在最近三個月內最長連續消費的天數分佈情況,考慮實施連續消費 10 天后積分三倍的促銷活動

一個月中有多少用戶在 24 小時連續操作了查看商品後加入購物車併購買的的動作,有多少用戶在中間步驟中放棄?

……

(爲了便於理解,這些例子已經做了簡化,實際情況的運算還要複雜很多)

這類過程性運算,用 SQL 寫出來的難度就很大,經常還要寫 UDF 才能完成。如果 SQL 寫都寫不出來,那麼 SQL 的使用效果將大打折扣。

開發效率低導致性能低

複雜 SQL 的執行效率往往也很低,這就又回到性能的問題了,實際上開發效率和計算性能是密切相關的,很多性能問題本質上是開發效率造成。

複雜 SQL 的優化效果很差,在嵌套幾層之後,數據庫引擎也會暈掉,不知道如何優化。提高這類複雜運算的性能,指望計算平臺的自動優化就靠不住了,根本手段還要靠寫出高性能的算法。象過程式運算中還常常需要保存中間結果以複用,SQL 需要用臨時表,多了 IO 操作就會影響性能,這都不是引擎優化能解決的事情,必須要去改寫計算過程。

所以,本質上,提高性能還是降低開發難度。軟件無法提高硬件的性能,只能想辦法設計複雜度更低的算法,而如果能夠快速低成本地實現這些算法,那就可以達到提高性能的目標。如果語法體系難以甚至沒辦法描述高性能算法,必須迫使程序員採用複雜度較高的算法,那也就很難再提高性能了。優化 SQL 運算無助於降低它的開發難度,SQL 語法體系就是那樣,無論怎樣優化它的性能,開發難度並不會改變,很多高性能算法仍然實現不了,也就難以實質性地提高運算性能。

編寫 UDF 在許多場景時確實能提高性能,但一方面開發難度很大,另一方面這是程序員硬寫的,也不能利用到 SQL 引擎的優化能力。而且經常並不能將完整運算都寫成 UDF,只能使用計算平臺提供的接口,仍然要在 SQL 框架使用它的數據類型,這樣還是會限制高性能算法的實現。

根本的解決方法,還是要讓大數據平臺真地有一些更好用的語法。

解法

使用開源集算器 SPL 就可以作爲 SQL 很好的替代和延伸,作爲大數據平臺專用的計算語言,延續 SQL 優點的同時改善其缺點。

SPL 是一款專業的開源數據計算引擎,提供了獨立的計算語法,整個體系不依賴關係數據模型,因此在很多方面都有長足突破,尤其在開發效率和計算性能方面。下面來盤點一下 SPL 都有哪些特性適用於當代大數據平臺。

強集成性

首先是集成性,不管 SPL 多優秀,如果與大數據平臺無法結合使用也是白費。要在大數據平臺中使用 SPL 其實很方便,引入 jar 包就可以使用(本身也是開源的,想怎麼用就怎麼用)。SPL 提供了標準 JDBC 驅動,可以直接執行 SPL 腳本,也可以調用 SPL 腳本文件。


Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
Statement st = connection.();
//直接執行SPL腳本
//ResultSet rs = st.executeQuery("=100.new(~:baseNum,~*~:square2)");
//調用SPL腳本文件
CallableStatement st = conn.prepareCall("{call SplScript(?, ?)}");
st.setObject(1, 3000);
st.setObject(2, 5000);
ResultSet result=st.execute();
...

高效開發

敏捷語法

在結構化數據計算方面,SPL 提供了獨立的計算語法和豐富的計算類庫,同時支持過程計算使得複雜計算實現也很簡單。前面舉的計算股票最長連漲天數的例子,用 SPL 實現是這樣的:

ToetKY

按交易日排好序,將連漲的記錄分到一組,然後求最大值 -1 就是最長連續上漲天數了,完全按照自然思維實現,不用繞來繞去,比 SQL 簡單不少。

再比如根據用戶登錄記錄列出每個用戶最近一次登錄間隔:

MV1KdJ

支持分步的 SPL 語法完成過程計算很方便。

SPL 提供了豐富的計算類庫,可以更進一步簡化運算。

直觀易用開發環境

同時,SPL 還提供了簡潔易用的開發環境,單步執行、設置斷點,所見即所得的結果預覽窗口…,開發效率也更高。

多數據源支持

SPL 還提供了多樣性數據源支持,多種數據源可以直接使用,相比大數據平臺需要數據先 “入庫” 才能計算,SPL 的體系更加開放。

SPL 支持的部分數據源(仍在擴展中…)

不僅如此,SPL 還支持多種數據源混合計算,充分發揮各類數據源自身的優勢,擴展大數據平臺的開放性。同時,直接使用多種數據源開發實現上也更簡單,進一步提升開發效率。

熱切換

SPL 是解釋執行的,天然支持熱切換,這對 Java 體系下的大數據平臺是重大利好。基於 SPL 的大數據計算邏輯編寫、修改和運維都不需要重啓,實時生效,開發運維更加便捷。

高計算性能

前面我們說過,高性能與高開發效率本質上是一回事,基於 SPL 的簡潔語法更容易寫出高性能算法。同時,SPL 還提供了衆多高性能數據存儲和高性能算法機制,SQL 中很難實現的高性能算法及存儲方案用 SPL 卻可以輕鬆實現,而軟件提高性能關鍵就在於算法和存儲。

例如前面說過的 TopN 運算,在 SPL 中 TopN 被理解爲聚合運算,這樣可以將高複雜度的排序轉換成低複雜度的聚合運算,而且很還能擴展應用範圍。

ylxUt0

這裏的語句中沒有排序字樣,也不會產生大排序的動作,在全集還是分組中計算 TopN 的語法基本一致,而且都會有較高的性能。

以下是一些用 SPL 實現的高性能計算案例:

開源 SPL 提速保險公司團保明細單查詢 2000+ 倍
開源 SPL 提升銀行自助分析從 5 併發到 100 併發
開源 SPL 提速銀行用戶畫像客羣交集計算 200+ 倍
開源 SPL 優化銀行預計算固定查詢成實時靈活查詢
開源 SPL 將銀行手機賬戶查詢的預先關聯變成實時關聯
開源 SPL 提速銀行資金頭寸報表 20+ 倍
開源 SPL 提速銀行貸款協議跑批 10+ 倍
開源 SPL 優化保險公司跑批優從 2 小時到 17 分鐘
開源 SPL 提速銀行 POS 機交易報表 30+ 倍
開源 SPL 提速銀行貸款跑批任務 150+ 倍
開源 SPL 提速資產負債表 60 倍

再多說兩句,SPL 沒有基於關係數據模型,而是採用了一種創新的理論體系,在理論層面就進行了創新,篇幅原因這裏不再過多提及 寫着簡單跑得又快的數據庫語言 SPL這裏有更細緻一些的介紹,感興趣的小夥伴也可以自行搜索,下載。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/m_-x6W-feUyFrHJKfCc2oQ