圖加速數據湖分析-GeaFlow和Apache Hudi集成

表模型現狀與問題

關係模型自1970年由埃德加·科德提出來以後被廣泛應用於數據庫和數倉等數據處理系統的數據建模。關係模型以表作爲基本的數據結構來定義數據模型,表爲二維數據結構,本身缺乏關係的表達能力,關係的運算通過Join關聯運算來處理。表模型簡單且易於理解,在關係模型中被廣泛使用。
隨着互聯網信息技術的發展,處理的數據規模越來越大,大數據系統應運而生。表模型作爲重要的數據模型依然被Spark/Hive/Flink等主流大數據引擎所採用,表模型之上的SQL查詢語言也被廣泛使用在大數據分析處理中。然而隨着應用場景的豐富和處理數據規模的變大,表模型的問題也越來越多的暴露出來。

  • 首先,關係運算成本高

表模型本身缺乏關係描述能力,只能通過Join運算來完成關係的計算。無論在批處理系統裏面還是流計算系統中,Join都是非常重的操作,需要大量的數據shuffle和計算開銷,在流計算系統中,還需要存放左右兩張流錶的歷史狀態,存儲消耗極高。

  • 其次,數據冗餘時效性低

數倉分析的場景爲了提高數據查詢性能,往往將多張表提前物化成一張大寬表。大寬表雖然可以加速查詢性能,然而其數據膨脹和冗餘非常嚴重。需要將多張表Join成一張表,表與表之間一對多的關聯關係導致一張表的數據通過關聯會放大多份,造成數據量指數級膨脹和冗餘。而且寬表一旦生成,如需添加新的表進來,需要重新生成新寬表,計算開銷大,不靈活。另外,基於Join方式成本高,基於寬表方式很難實現數倉實時化。

  • 最後,無法支持複雜關係查詢

基於SQL join方式很難描述複雜關係查詢,比如查詢一個人4度以內所有好友或者查詢最短路徑等。這些複雜關聯關係通過SQL表的join方式很難描述。

圖模型解決方案

圖是關係的天然描述

圖是對關係的一種天然描述,圖模型是一種以點和邊作爲基本單元定義的數據模型天然可以描述關聯關係。在圖模型裏面以點代表實體,以邊代表關係。比如在人際關係圖裏面,每一個人可以用一個點來表示,人和人之間的關係通過邊來表示,人與人之間可以存在各種各樣的複雜關係,這些關係都可以通過不同的邊來表示。所以圖模型裏面天然就包含關係,是對關係最自然的表達。

圖是關係的物化

圖模型中本身包含點邊關係的定義,在數據存儲層面會按照點邊關係存放數據,點和其鄰邊會存儲在一起。所以圖存儲層面對關係做了物化,相比與表的Join方式,可以獲取更好的關聯計算性能。相比寬表的關係物化方式,由於圖結構本身的點邊聚合性,不會出現寬表展開導致的數據膨脹,其存儲空間會更小,如下圖所示。

圖加速數據查詢

利用圖的關係物化的能力,可以加速關係運算的查詢,如下例子:
學生、課程和教師三個實體表,實體之間存在選課(selectCourse)、考試(examination)和教學(teach)三種關係.這些實體之間的關係查詢可以通過圖查詢來表示。

  • 查詢數學考試成績前十的學生及其分數
select s.id, s.name, e.score 
from student s join examination e join c course
on s.id = s.student_id and e.course_id = c.id
where c.name = 'math'
order by e.score desc limit 10

對應圖查詢:

Match(s:student) - [e:examination]->(c:course where c.name = 'math')
Return s.id, s.name, e.score order by e.score desc limit 10
  • 查詢選課人數最多的老師Top 3
select tr.id, count(s.id) 
from student s join selectCourse sc join course c 
join teach th join teacher tr
on s.id = sc.student_id and sc.course_id = c.id and c.id = th.course_id
and th.teacher_id = tr.id
order by count(s.id) desc
limit 3

對應圖查詢:

Match(s:student)-[sc:selectCourse]->(c:course)<-[th:teach]-(tr:teacher)
Return tr.id, count(s.id) as cnt order by cnt desc limit 3

圖模型和表模型關係

圖模型本身包含點數據集和邊數據集,點邊數據集來源於表數據,比如Hive表、Hudi表等。所以,圖模型是表模型的超集,是對錶模型的補充和完善。圖模型可以起到類似寬表的作用,物化表的關係,同時能更靈活的定義關係,消耗更小的存儲開銷.

GeaFlow和Hudi集成

GeaFlow(品牌名TuGraph-Analytics)是螞蟻自研的分佈式實時圖計算引擎,兼顧離線圖計算能力。GeaFlow以圖模型作爲基本的數據模型,在圖模型基礎之上定義了一套圖計算的編程接口,同時和流式處理能力相結合,實現了流式圖計算的能力。在DSL語言層面,GeaFlow將表處理語言SQL和圖查詢語言ISO/GQL相結合,實現了圖表一體的數據分析能力。通過GeaFlow圖計算的能力,很好的解決了大規模數據關聯關係計算的問題。

Hudi是業界熱門的數據湖格式,旨在解決數據湖中數據的變更管理問題。Hudi使用了一種基於日誌的存儲方式,可以支持數據的實時增量、刪除和更新,並且能夠保證數據的一致性和可靠性。Hudi的核心思想是將數據劃分成小的數據塊,每個數據塊都包含了數據的變更歷史,可以通過增量方式和全量方式讀取和寫入數據。Hudi支持多種數據格式,包括Parquet、ORC、CSV等,並且可以與Hadoop、Spark、Flink等大數據處理框架無縫集成,可用於數據湖的建設和數據管理。Hudi的出現大大簡化了數據湖的數據變更管理和數據處理流程,是一個非常優秀的數據管理框架。

GeaFlow支持和多種數據源集成,包括Hudi。利用GeaFlow圖計算的能力,可以對Hudi數據湖數據做關係物化,加速DWD層的查詢性能和時效性,同時也可以基於圖數據做更多複雜的圖算法分析。

以下爲GeaFlow使用Hudi構圖,然後進行4度環路查找和SSSP算法計算的例子:

圖定義

我們首先需要定義張圖,使用Create Graph語法定義如下:

CREATE GRAPH IF NOT EXISTS friend (
  Vertex person (
    id bigint ID,
    name varchar
  ),
  Edge knows (
    srcId bigint SOURCE ID,
    targetId bigint DESTINATION ID,
    weight double
  )
) WITH (
  storeType='rocksdb',
  shardCount = 4
);

這張圖定義包含點表person和邊表knows. 點表person定義了點的屬性信息和id字段,id字段唯一標識圖裏面的點,爲點表的主鍵,通過ID關鍵字來定義。邊表knows裏面定義好友關係,srcId爲關係的起點,通過SOURCE ID關鍵字定義;targetId爲關係的目標點,通過DESTINATION ID關鍵字定義。weight字段則爲邊的一個屬性字段。一張圖的點邊或者邊表可以包含零個或者多個屬性字段。

Hudi表定義

首先我們需要定義一張Hudi點表和Hudi邊表:

set geaflow.dsl.window.size = -1;

CREATE TABLE IF NOT EXISTS hudi_person (
  id BIGINT,
  name VARCHAR
) WITH (
  type='hudi', -- hdfs 配置,也可通過HADOOP_HOME環境變量獲取
  `geaflow.file.persistent.config.json` = '{\'fs.defaultFS\':\'namenode:9000\'}',
  geaflow.dsl.file.path='/path/to/hudi_person'
);

CREATE TABLE IF NOT EXISTS hudi_knows (
  src_id BIGINT,
  target_id BIGINT,
  weight DOUBLE
) WITH (
  type='hudi', -- hdfs 配置,也可通過HADOOP_HOME環境變量獲取
  `geaflow.file.persistent.config.json` = '{\'fs.defaultFS\':\'namenode:9000\'}',
  geaflow.dsl.file.path='/path/to/hudi_knows'
);

GeaFlow是一個流式圖計算引擎,數據源按照window size切分成一系列的window, 引擎會依次處理這些window的數據。如果window size設置爲-1,則代表一個All Window,即一次全量處理所有數據。對於Hudi這樣的批數據源接口,需要設置window size爲-1來處理。

構圖

構圖是將外部數據表的數據寫入到圖裏面,可以通過Insert語句來完成。如下語句,分佈將hudi表裏面的數據寫入到friend圖的person表和knows表裏面,完成圖數據的構建。

INSERT INTO friend.person(id, name)
SELECT
id, name
FROM hudi_person
;

INSERT INTO friend.knows
SELECT src_id, target_id, weight * 10
FROM hudi_knows
;

圖計算

接下來是對構建好的圖數據做圖計算,我們以SSSP(單源最短路徑)和四度環路檢查爲例進行介紹:

CREATE TABLE IF NOT EXISTS sssp_result (
  vid int,
  distance bigint
) WITH (
  type='file',
  `geaflow.file.persistent.config.json` = '{\'fs.defaultFS\':\'namenode:9000\'}',
  geaflow.dsl.file.path='/path/to/result'
);
-- 定義計算使用的圖
USE GRAPH friend;

INSERT INTO sssp_result
CALL SSSP(1) YIELD (vid, distance)
RETURN vid, distance
;

-- 圖算法執行
INSERT INTO result
CALL SSSP(1) YIELD (vid, distance)
RETURN vid, distance
;

首先需要定義一個結果表result來存放計算結果,然後通過USE GRAPH命令來設置當前計算用到的圖。最後通過CALL語句來執行SSSP算法(其中SSSP算法的入參爲起始點id), 並將計算結果寫入結果表。
四度環路匹配如下語句,通過Match匹配一個4度環路的pattern,然後將結果寫出結果表.

CREATE TABLE IF NOT EXISTS match_result (
  a_id bigint,
  b_id bigint,
  c_id bigint,
  d_id bigint,
  a1_id bigint
) WITH (
  type='file',
  `geaflow.file.persistent.config.json` = '{\'fs.defaultFS\':\'namenode:9000\'}',
  geaflow.dsl.file.path='/path/to/result2'
);
-- 四度環路匹配
INSERT INTO match_result
SELECT
a_id,
b_id,
c_id,
d_id,
a1_id
FROM (
  MATCH (a:person) -[:knows]->(b:person) -[:knows]-> (c:person)
  -[:knows]-> (d:person) -> (a:person)
  RETURN a.id as a_id, b.id as b_id, c.id as c_id, d.id as d_id, a.id as a1_id
);

總結

本文主要分析了表模型的現狀和問題,然後介紹了圖模型在處理關係運算上的優勢,接着介紹了圖計算引擎GeaFlow和數據湖格式hudi的整合,利用圖計算引擎加速數據湖上的關係運算.

GeaFlow已正式開源,歡迎大家關注!!!

GitHub地址:https://github.com/TuGraph-family/tugraph-analytics

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