天天看點

因為該列沒有包含在聚合函數或 group by 子句中。_TigerGraph累加器 與 SQL中GROUP BY 的比較...

因為該列沒有包含在聚合函數或 group by 子句中。_TigerGraph累加器 與 SQL中GROUP BY 的比較...

對于生産環境的圖資料庫選型,圖查詢語言一直是使用者首要考慮的問題之一。 一些考慮因素包括但不限于易用性、表達性和與 ISO 标準的一緻性。 當談到将圖資料庫投入生産時,我們的經驗表明,足夠的表達能力是首位的。

在之前的部落格中,我們剖析了累加器的基本語義和使用模式。 我們得到了很多回報。 最常見的問題之一是,累加器是否可以實作在 SQL 中 GROUP BY聚合操作?

答案是可以的,不僅如此,通過累加器甚至可以實作一些SQL難以實作的操作! 累加器可以以簡潔和清晰的形式表達特定類型,實作高性能查詢。 對于這類查詢,按照 SQL 的GROUP BY聚合看起來很麻煩,并且會導緻浪費的計算。

在本文中,我們将繼續讨論累加器,通過GSQL的聚合文法模拟不同的 SQL GROUP BY 語句。 這個練習揭示了通過聚合使用累加器優于傳統 SQL GROUP 的好處。

模拟 SQL 的GROUP BY 聚合

累加器在GSQL的Select-from-where 查詢塊中的 Accum 子句部分進行值的聚合計算。 結果表明,這種查詢塊結構可以表示所有正常 SQL 的GROUP BY聚合。

對于 SQL 的5個内置聚合函數(MIN / MAX / SUM / COUNT / AVG) ,GSQL 對應了5個不同的累加器類型(MINAccum / MAXAccum / SUMAccum / SUMAccum / AVGAccum)。 這裡我們展示一個簡單的示例,它使用 GSQL 内置的 累加器實作 SQL 的 GROUP BY聚合。

例一:

給定一個 Employee 表,其中每一行存儲雇員的姓名、性别和目前薪水,我們希望找出每個性别的最低、最高、總和平均薪水是多少,以及每個性别的雇員總數是多少? 在 SQL 中,這個查詢可以通過一個查詢塊表示,如下所示。

SELECT gender, 
      MIN(salary) AS MIN_salary,
      MAX(salary) AS MAX_salary,
      AVG(salary) AS AVG_salary,
      SUM(salary) AS tot_salary,
      COUNT(*)    AS tot_COUNT
FROM Employee
GROUP BY gende
           

如下所示:在 GSQL,我們可以通過多個累加器來實作相同的結果。

GROUP BYAccum<string gender, 
            MINAccum<double> MIN_salary,
            MAXAccum<double> MAX_salary, 
            AVGAccum<double> AVG_salary, 
            SUMAccum<double> tot_salary, 
            SUMAccum<int>  tot_COUNT> @@gender_aggs;
                          
R = SELECT e
    FROM Employee:e 
    Accum @@gender_aggs += (e.gender->e.salary, e.salary, e.salary, e.salary, 1);
           

在上面的 GSQL 查詢中,我們聲明一個名為@@ gender aggs 的 GROUP BYAccum全局累加器。 它将性别作為GROUP BY的KEY,其餘5個累加器作為聚合器,以聚合每個組的VALUE值。 對于雇員這個頂點類型,我們綁定一個變量“ e” ,Accum 子句将并行地将KEY e.gender 和 VALUE (e.salary,e.salary,e.salary,e.salary,1)發送到 全局累加器@@gender_aggs中。

SQL 和 GSQL 查詢都可以通過單遍算法實作,其中我們浏覽一次員工表,并計算每個聚合器的聚合結果。

通常,正常的 SQL GROUP-by 聚合可以指定為

SELECT K1,K2,...,Kn, agg1(A1),agg2(A2),agg3(A3)..., aggm(Am)
FROM ...
GROUP BY K1,K2,...,Kn
           

以 Ki 作為按鍵組,以 Aj 作為聚合屬性。 在 GSQL 中,這是通過 Accum 子句實作的

Accum A += (K1,K2,...,Kn → A1,A2,...,Am)
           

其中 A 被聲明為一個包含K1,K2,… ,Kn,Acc1,Acc2,… Accm的 GROUP BYAccum類型的累加器。

模拟 SQL 的進階聚合

累加器同樣可以表示多個 GROUP BY 聚合,例如 SQL GROUP BY 子句的 CUBE、 ROLLUP 和 GROUPING SET 擴充。

它們各自計算分組屬性的幾個子集的聚合,外部統一每個分組的結果。 其中 GROUPING SETS 擴充是最靈活的擴充,允許對分組屬性子集進行目标選擇。

例二:

例如,對于一個定義了三個分組集(k1,k2,k3)的GROUPBY子句,GROUPING SETS((k1,k2),k3)在 GSQL 中可以按照以下格式實作

Accum A += (k1,k2,null → a1,a2,a3),
      A += (null,null,k3 → a1,a2,a3)
           

類似地,CUBE (k1,k2,k3)擴充可以用8個 累加器來描述(對應{ k1,k2,k3}的8個子集)和 ROLLUP (k1,k2,k3)擴充可以用4個累加器來描述(分别對應{ k1,k2,k3} ,{ k1,k2} ,{ k1} ,{ k1} ,{{})。

TigerGraph 是目前 SQL/PGQ 和 GQL 标準草案的積極參與者和貢獻者,我們調查了市場上其他流行的圖查詢語言,現有的圖查詢語言都不支援GROUP BY文法擴充(CUBE / ROLLUP / GROUPING SET)。 相比之下,如上面的示例所示,GSQL 的累加器便于直接添加 CUBE、 ROLLUP 和 GROUPING SET 關鍵字,将其作為文法糖來保證預期的單次周遊得到結果。

SQL 聚合中 CUBE / ROLLUP / GROUPING SET 的缺陷

CUBE、 ROLLUP 和 GROUPING SET 本質上是友善的文法糖,可以通過屬性指定組的子集,我們可以在這些屬性上計算所有的聚合結果。 這些GROUP BY文法擴充的一個缺點是,它們不允許 SQL 使用者将 SELECT 子句中的不同聚合指定為不同的分組集。 也就是說,出現在 SELECT 子句上的任何聚合函數将會作用于進階GROUP BY文法糖産生的每個分組集。

當使用者希望将特定的聚合器綁定到不同的分組集時,這将導緻浪費計算。

示例3每個GROUPING SET的造成的聚合浪費

假設我們希望分别對GROUPING SET(K1)、(K2)、(K3)進行求和、最小值 和 平均值 聚合計算,那麼 GROUPING SET 語義将強制計算每個分組集合的所有三個聚合(其中兩個是不需要的)。 在 GSQL 形式中,它表示為

Accum A1 += (k1 → a1, a2, a3), A2 += (k2 → a1, a2, a3),A3 += (k3 → a1, a2,a3)  
           

相比之下,在 GSQL 中,我們可以為每個分組集合 Ki 設定一個單獨的累加器 Ai,每個 Ai 隻執行所需的聚合:

Accum A1 +=(k1 → a1), A2 += (k2 → a2), A3 += (k3 → a3)
           

很明顯,聚合器的精細綁定避免了對 k1進行 a1、 a3計算 ,對k2進行 a1、 a3計算,以及對k3進行 a1、 a2計算,這是一種浪費的工作。

量化聚合浪費

經我方實驗報告顯示,我們量化了基于 GSQL 累加器的聚合對比SQL聚合所節省的資源消耗。

在周遊圖的過程中,浪費在不需要的聚合計算中的開銷會造成可測量的性能損失。 我們通過一個實驗來說明這一點,該實驗比較了兩種類型的多聚合的性能:

基于累加器的

SQL GROUPING SET (這是 SQL選項中最有效的一個,因為它避免了計算不需要的分組集——但是,像其他所有選項一樣,它不能避免計算每個分組集合不需要的聚合)。

資料: 為了使用可伸縮的圖形,我們采用了 LDBC SNB 基準資料,使用的資料大小從1GB 到1TB 不等。

查詢:我們調整了 SNB 提供的查詢場景來計算多個聚合。 我們在這裡列舉其中一個查詢(它的衡量方式可用于其他查詢)。 這個查詢列舉了2010年至2012年間所有釋出的資訊中,

人們及他們所居住的城市和他們喜歡的評論(人、城市和評論被模組化為頂點,之間的關系被模組化成邊)

它計算三個GROUP SET,每個集合都有自己的聚合:

1、每(評論出版年) ,它計算

•最近的20條評論,優先取評論最長的評論,

•最早的20條評論,優先最長的評論,

•20條最長的評論,優先最新的評論,

•20條最短的評論,優先最新的評論,

•最年長作者的十大評論,優先最長的

•最年輕作者的十大評論,優先最長的。

2、每(作者的城市,浏覽器類型,出版年份,月份,評論長度) ,計算評論次數

3、每(作者的城市,性别,浏覽器類型,出版年份和月份) ,計算平均評論長度

我們使用 GSQL 表達查詢,遵循兩種風格:

Q_gs 使用累加器模拟 SQL GROUPING SET 聚合,如示例3所示,滿足 GROUPING SET 語義前提下,G_qs 為三個分組集中的每一個計算所有8個聚合。 這個查詢釋出在 GitHub 上。 (注意,這個查詢需要 TigerGraph 3.0特性,其中 HeapAccum 可以在 GROUP BYAccum 中使用)。

使用适當的累加器,Q_acc 隻為每個分組集計算所需的聚合,如示例3所示。 這個查詢亦釋出在 GitHub 上。

我們測量的内容: 我們測量了由 SNB 生成器生成的圖的 Q_gs 和 Q_acc 的運作時間,在标度因子 SF-1(1GB)、 SF-10(10GB)、 SF-100(100GB)和 SF-1000(1TB)上。 對于每個圖形,我們運作每個查詢5次,記錄運作時間的中位數。

結果:我們觀察了以下查詢的運作時間(全部以秒表示) ,結果顯示,在圖大小從1GB 到1TB 不等的情況下,

與 SQL 風格的聚合相比,基于累加器的聚合最多可以提高3倍的計算效率。

因為該列沒有包含在聚合函數或 group by 子句中。_TigerGraph累加器 與 SQL中GROUP BY 的比較...

平台:我們在一個類型為 r4.8 xlarge 的 Amazon EC2執行個體上按比例因子1、10和100加載圖表(并運作查詢)。 對于比例因子1000,我們使用了微軟Azure 3個節點的叢集,每個節點類型為 E64a v4(圖存儲和查詢執行都是基于 TigerGraph 3.0引擎做了分布式處理,這意味着使用者查詢不需要編輯)。

總結

我們對GSQL的累加器 和 SQL 風格的聚合做了詳盡的對比。 ,累加器不僅涵蓋了 SQL 風格聚合的表達能力,同時在簡潔性和避免浪費性方面具備一定的優勢。

我們設計累加器的目的是使圖分析查詢更容易編寫。 另一方面,它為針對特定類型的聚合查詢編寫單遍聚合查詢提供了簡潔性和靈活性,而 SQL GROUP BY聚合文法則不能輕松實作。 如本研究所示,SQL 使用者不能輕松地将單個聚合從 SELECT 子句綁定到一個GROUP SET上,而累加器是可以做到的。

在 GSQL 早期的設計(2015年夏天)中,使我們關注和興奮的是利用運作時屬性(局部累加器)和全局狀态變量(全局累加器)修飾圖拓撲,降低了編寫圖分析查詢的複雜度。 累加器是通過修飾頂點和查詢塊之間共享計算狀态的圖來實作強大和高效的組合結果的一種手段。 有了這些修飾,圖形分析變得簡單而有趣。 你同意嗎?

本文作者:烏明希

歡迎通過以下方式和我們交流:

TigerGraph中文技術社群:TigerGraph中文社群

TigerGraph官網:The First Native Parallel Graph

TigerGraph微信公衆号:TigerGraph