李 鋼,茅海泉
(南瑞集團有限公司(國網(wǎng)電力科學(xué)研究院有限公司),南京 211000)
(江蘇瑞中數(shù)據(jù)股份有限公司,南京 210012)
在電網(wǎng)系統(tǒng)中產(chǎn)生的準(zhǔn)實時數(shù)據(jù)[1],可以被應(yīng)用在調(diào)度、在線監(jiān)測、計量等多種場景中.海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺(以下簡稱海量平臺)是南方電網(wǎng)公司面向數(shù)據(jù)資源統(tǒng)一管理及針對實時數(shù)據(jù)管理的有力支撐平臺,可以對生產(chǎn)運行過程中各業(yè)務(wù)應(yīng)用形成的實時歷史數(shù)據(jù)進行存儲、集中、整合、共享和分析,同時提供了標(biāo)準(zhǔn)統(tǒng)一的NOSQL訪問方式.
隨著電網(wǎng)規(guī)模的不斷擴大、信息系統(tǒng)的不斷升級擴展,準(zhǔn)實時數(shù)據(jù)呈現(xiàn)海量的特點,具有明顯的大數(shù)據(jù)[2]特征.Spark[3]、HBase[4]等大數(shù)據(jù)服務(wù)平臺是目前流行的大數(shù)據(jù)解決方案,得到廣泛的應(yīng)用.大數(shù)據(jù)服務(wù)平臺可以運用到電網(wǎng)系統(tǒng)中,更好的解決海量準(zhǔn)實時數(shù)據(jù)的存儲、計算、分析等問題,具有很高的實用價值.大數(shù)據(jù)平臺可以通過JDBC與外部數(shù)據(jù)源進行連接,獲取電網(wǎng)檔案、模型等關(guān)系數(shù)據(jù).而海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺提供統(tǒng)一訪問接口UAPI不支持SQL查詢.如何將海量平臺中非結(jié)構(gòu)化的量測數(shù)據(jù)與模型、檔案等關(guān)系數(shù)據(jù)通過統(tǒng)一SQL訪問引擎結(jié)合起來,成為運用大數(shù)據(jù)服務(wù)平臺的關(guān)鍵問題.
本文采用分層的策略,在上層大數(shù)據(jù)平臺與底層海量平臺間設(shè)計實現(xiàn)專門的SQL引擎.大數(shù)據(jù)平臺通過該引擎,運用SQL的方式訪問海量平臺中的數(shù)據(jù).SQL引擎基于PostgreSQL設(shè)計實現(xiàn),能解析大數(shù)據(jù)層的SQL語句并通過UAPI獲取海量平臺數(shù)據(jù).現(xiàn)場測試結(jié)果驗證了該接口的有效性.
海量平臺中,非結(jié)構(gòu)化數(shù)據(jù)主要存儲在實時數(shù)據(jù)庫中.目前國產(chǎn)的實時數(shù)據(jù)庫僅支持簡單的SQL查詢,無法支持復(fù)雜SQL的查詢,如與結(jié)構(gòu)化數(shù)據(jù)結(jié)合的嵌套查詢或者join查詢等.因此,需要開發(fā)專用的SQL引擎來實現(xiàn)結(jié)構(gòu)化數(shù)據(jù)與非結(jié)構(gòu)化數(shù)據(jù)的聯(lián)合查詢,為大數(shù)據(jù)應(yīng)用提供數(shù)據(jù).基于PostgreSQL的SQL引擎是一種很有效的解決方案.
PostgreSQL是由加州大學(xué)伯克利分校[5,6]開發(fā)的開源數(shù)據(jù)庫系統(tǒng),可以運行在Windows、Linux等多種平臺上.PostgreSQL是世界頂級關(guān)系數(shù)據(jù)庫之一,被廣泛運用在醫(yī)療、天文、商業(yè)等領(lǐng)域[7].PostgreSQL的主要技術(shù)特點包括:
1)標(biāo)準(zhǔn)通用.PostgreSQL基于廣泛應(yīng)用的關(guān)系數(shù)據(jù)模型,遵循SQL國際標(biāo)準(zhǔn).PostgreSQL為應(yīng)用開發(fā)提供了符合標(biāo)準(zhǔn)的 ODBC3.0、JDBC3.0、OLEDB 2.7和嵌入式 SQL 接口.PostgreSQL經(jīng)過大量實際應(yīng)用的磨合與驗證,已成為標(biāo)準(zhǔn)、通用、安全、穩(wěn)定、實用、高效的數(shù)據(jù)存儲與管理平臺.
2)海量存儲.PostgreSQL結(jié)合結(jié)構(gòu)化查詢語言的操作能力和過程化語言的數(shù)據(jù)處理能力,可以有效地支持大規(guī)模數(shù)據(jù)存儲與存取,如TB級的數(shù)據(jù)庫的表空間、GB級的 BLOB 二進制大對象和 CLOB 文本大對象等,并通過各種約束保證數(shù)據(jù)的完整性和安全性.
3)Postgres_fdw.Postgres_fdw為PostgreSQL數(shù)據(jù)庫的外部數(shù)據(jù)封裝器,可以用來訪問存儲在數(shù)據(jù)庫外的數(shù)據(jù).Postgres_fdw支持支持標(biāo)準(zhǔn)的SQL select語句,不支持insert,update等語句,通過Postgres_fdw,可采用統(tǒng)一的SQL訪問不同數(shù)據(jù)源的數(shù)據(jù).
4)訪問高效.PostgreSQL采用c語言編寫,運用多進程模型,支持高并發(fā)訪問.將結(jié)果存儲在內(nèi)存中,有效避開無用的磁盤讀寫,具有高效訪問的特點.
基于以上技術(shù)優(yōu)勢,本文采用PostgreSQL來設(shè)計統(tǒng)一SQL引擎.
統(tǒng)一訪問接口(UAPI)是海量平臺對外提供的一套實時數(shù)據(jù)訪問接口,UAPI不支持SQL訪問.UAPI屏蔽了底層數(shù)據(jù)庫的具體實現(xiàn)細節(jié)及差異,對外提供統(tǒng)一的訪問接口為上層應(yīng)用服務(wù),對用戶來說是只有一個邏輯實時數(shù)據(jù)庫,從而實現(xiàn)了透明性以及分布式訪問.
實時數(shù)據(jù)庫統(tǒng)一訪問接口的實現(xiàn)以標(biāo)準(zhǔn)C/C++語言為編程語言并充分考慮接口的跨平臺性,接口至少支持Windows、Linux等平臺.
在電網(wǎng)系統(tǒng)中運用大數(shù)據(jù)存儲、分析工具,需要實現(xiàn)將底層海量平臺的數(shù)據(jù)導(dǎo)入到大數(shù)據(jù)平臺.大數(shù)據(jù)平臺通過JDBC接口連接外部數(shù)據(jù)源,而海量平臺已實現(xiàn)UAPI供外部調(diào)用.本文設(shè)計實現(xiàn)了基于PostgreSQL的SQL引擎,實現(xiàn)在大數(shù)據(jù)端通過SQL的方式訪問、抽取海量平臺實時數(shù)據(jù).本文訪問引擎實現(xiàn)的主要功能包括:
不包括where條件的查詢.用于查詢所有測點的信息.
帶where條件的測點查詢.查詢符合特定條件的測點信息.此處的條件包括測點標(biāo)識和測點名.
原始值、斷面、實時值、差值[8]查詢.查詢測點不同類型的值信息.
模糊查詢.便于查詢符合特定條件的相關(guān)測點集信息.
帶子查詢的where條件查詢.可以在查詢語句中嵌套子查詢,方便更深層次的應(yīng)用需求.
指定字段的查詢.用于查詢測點的部分信息.
大數(shù)據(jù)平臺與海量平臺間通過本文的訪問插件進行連接.具體架構(gòu)如圖1所示.
圖1 整體架構(gòu)圖
如圖1,整體架構(gòu)分為三層,分別是:
接口層: 接口層是大數(shù)據(jù)平臺的管理接口,主要部署SparkSQL[9].SparkSQL支持在Java,Scala,Python和R等高級語言中使用標(biāo)準(zhǔn)的SQL語句在Spark中查詢結(jié)構(gòu)化數(shù)據(jù).大數(shù)據(jù)分析應(yīng)用調(diào)用SparkSQL接口實現(xiàn)對海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺的數(shù)據(jù)查詢和分析計算.
大數(shù)據(jù)平臺層: 大數(shù)據(jù)平臺是電網(wǎng)系統(tǒng)中大數(shù)據(jù)工具的部署層,主要涵蓋Spark、HDFS[10]和HBase.Spark負責(zé)準(zhǔn)實時數(shù)據(jù)的計算分析,HDFS和HBase解決實時歷史數(shù)據(jù)的存儲問題.
海量平臺層: 海量平臺層是目前電網(wǎng)系統(tǒng)中部署的實時數(shù)據(jù)管理平臺,負責(zé)對關(guān)系數(shù)據(jù)庫、實時數(shù)據(jù)庫等數(shù)據(jù)源的統(tǒng)一管理.在底層的數(shù)據(jù)源上是本文重點設(shè)計實現(xiàn)的SQL解析引擎.大數(shù)據(jù)訪問接口通過JDBC與大數(shù)據(jù)平臺連接,與底層的海量平臺通過UAPI連接.整體上,海量平臺作為大數(shù)據(jù)平臺的外部數(shù)據(jù)源,通過本文的訪問插件為上層提供數(shù)據(jù)支撐.
本文基于PostgreSQL的FDW(Foreign Data Wrapper)框架,設(shè)計海量平臺大數(shù)據(jù)訪問接口.本接口對外支持標(biāo)準(zhǔn)JDBC訪問方式.海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺大數(shù)據(jù)接口模塊架構(gòu)圖如圖2.
圖2 海量平臺大數(shù)據(jù)接口模塊架構(gòu)圖
海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺大數(shù)據(jù)接口模塊由三部分組成:
1)標(biāo)準(zhǔn)JDBC接口: 基于PostgreSQL對外提供的JDBC接口.用于與上層的Spark、HBase等連接.
2)PostgreSQL插件: 把PostgreSQL數(shù)據(jù)庫作為海量平臺大數(shù)據(jù)接口的一個功能插件.此處主要利用PostgreSQL的外部表訪問功能以及PostgreSQL對SQL語句的初步處理.
3)海量平臺FDW模塊: 基于PostgreSQL的FDW模塊,實現(xiàn)對海量平臺外部數(shù)據(jù)源的訪問.
整個大數(shù)據(jù)接口模塊中FDW模塊是本文的核心.FDW模塊位于接口的底層,負責(zé)連接PostgreSQL與海量平臺.FDW模塊將系統(tǒng)上層大數(shù)據(jù)部分傳入的SQL語句具體解析后調(diào)用相關(guān)的UAPI函數(shù)以實現(xiàn)準(zhǔn)實時數(shù)據(jù)的傳輸.
海量平臺SQL引擎位于海量平臺大數(shù)據(jù)接口的底層,基于PostgreSQL的FDW模塊設(shè)計實現(xiàn).整體的設(shè)計思路是將海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺中的數(shù)據(jù)抽象成PostgreSQL的外部表以支持訪問.
電網(wǎng)應(yīng)用中的準(zhǔn)實時數(shù)據(jù)主要包括測點信息和測點值信息,海量平臺FDW模塊相應(yīng)的映射為PostgreSQL的外部點表(upoint)和外部值表(uvalue).外部表的字段與實時數(shù)據(jù)中包含的信息相對應(yīng),例如外部值表中包含了測點標(biāo)識、時間戳、質(zhì)量位、值等字段.
基于上述思路,設(shè)計海量平臺FDW模塊的流程圖,如圖3所示.
海量平臺FDW模塊的主要實現(xiàn)流程包括:
連接海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺.與海量平臺建立連接是進行數(shù)據(jù)傳輸?shù)牡谝徊?
圖3 海量平臺FDW模塊實現(xiàn)流程圖
估算外部表大小.估算映射的外部表的大小,為后面查詢做準(zhǔn)備.
創(chuàng)建外部表查詢訪問路徑和掃描計劃節(jié)點.根據(jù)外部調(diào)用的IP地址是否是本地,設(shè)置不同的權(quán)重參數(shù);創(chuàng)建訪問路徑.
查詢初始化.主要是解析SQL語句.PostgreSQL對SQL語句進行了簡單的分詞處理,在FDW模塊中還需進一步分析SQL的語義信息,特別是SQL語句中where條件的處理.
執(zhí)行查詢并返回結(jié)果集.根據(jù)解析的SQL語句,調(diào)用對應(yīng)的UAPI函數(shù),將結(jié)果集組織成PostgreSQL中的記錄格式返回.
海量平臺SQL引擎的各功能點協(xié)調(diào)有序處理,能保證上層的SQL查詢正確解析;在映射成外部表的基礎(chǔ)上,調(diào)用相關(guān)UAPI函數(shù),順利完成訪問任務(wù).
在查詢外部表獲得具體的字段信息前,需要對外部表進行大小估算,以生成更優(yōu)的訪問路徑.本文中外部表包括外部點表和外部值表,分別設(shè)計了不同的大小估算方案.
外部點表大小估算: 首先查詢出總共的點數(shù),然后乘以每個點結(jié)構(gòu)所占的大小即可得整體點表的大小.
外部值表大小估算方案較復(fù)雜,具體流程如圖4所示.
外部值表大小估算: 如圖4,在海量平臺中,每個測點包含的值的個數(shù)不等,不能簡單的根據(jù)單個測點值的個數(shù)乘以測點總數(shù)來估算.而海量平臺中測點數(shù)在千萬級別,采用逐個測點查詢累加的方式會嚴重損害效率.本文采用隨機抽樣的方式,抽取總點數(shù)的二十分之一,計算此部分的測點值總個數(shù),最后乘以比例得到整體的估計值.
圖4 外部值表大小估算方案示意圖
SQL語句解析是查詢過程中的重要一環(huán).海量平臺FDW模塊在PostgreSQL詞法分析的基礎(chǔ)上,結(jié)合本系統(tǒng)的查詢要求,進行SQL語句的補充改造與語義解析,方便查詢時對應(yīng)到具體的UAPI函數(shù).SQL語句解析的整體框架如圖5所示.
圖5 SQL語句解析框架圖
SQL語句解析主要包括以下解析過程:
根據(jù)select后的字段,確定最終返回結(jié)果的內(nèi)容項.如“select name,tagtype,compress”表示需要返回測點的名稱、測點類型以及是否壓縮等信息.
根據(jù)from后的字段,確定查詢的是點信息或者是值信息.如“from upoint”表示查詢的是點信息,而“from uvalue”表示返回的是值信息,具體是何種值還需進一步判斷.
解析Where后的信息,獲得UAPI函數(shù)調(diào)用時的參數(shù).按照變量、常量、子查詢、關(guān)系操作符、bool值的分類方法,對每個分詞進行處理.
變量確定給出的信息類型,常量確定信息的具體值.對于id以范圍給出的(between A and B等形式),拆封成單個具體數(shù)值.涉及時間的,轉(zhuǎn)換成海量平臺所用時區(qū)的時間.如“where id between 100 and 135” id是變量,100和135是常量,id區(qū)間根據(jù)UAPI的調(diào)用規(guī)則轉(zhuǎn)換成100,101,102,…,135的形式.
對于包含子查詢的,先執(zhí)行子查詢并將結(jié)果傳遞給父查詢.涉及關(guān)系操作符和bool值的,需要將兩側(cè)的信息分別遞歸處理.如“where id=100 or id=109”‘or’是bool值,需要將兩側(cè)信息‘id=100’和‘id=109’分別遞歸到where子句層繼續(xù)處理.
增加mode和step字段.根據(jù)mode字段的值區(qū)分查詢測點值的具體形式(實時值、插值、斷面和原始值).對于查詢差值的,根據(jù)step字段確定每次的查詢步長.如“mode=3 and step=1500”表示查詢的是差值,且查詢步長是1500ms.
綜合來看,SQL語句“select * from uvalue where id=4000000 or id=4000001 and time > ‘2016-02-25 16:47:50.10’ and time < ‘2016-02-25 16:50:52.10’ and mode=3 and step=1000;” 表示查詢id為4000000和4000001的測點在‘2016-02-25 16:47:50.10’和‘2016-02-25 16:50:52.10’時間段內(nèi)的差值信息,查詢步長為1000 ms.
創(chuàng)建外部表,執(zhí)行create foreign table語句,為每個需要訪問的遠程表創(chuàng)建外部表.在本系統(tǒng)中就是創(chuàng)建外部點表和外部值表.
正確執(zhí)行上述步驟后,大數(shù)據(jù)訪問插件即安裝完成.在大數(shù)據(jù)端可以通過SQL語句訪問底層的實時數(shù)據(jù)了.
為了驗證SQL引擎功能的正確性,基于海量平臺進行了相關(guān)的測試.
測試中,選用的海量平臺中關(guān)系庫表有3000萬條數(shù)據(jù)[10].
海量平臺存儲了大量有價值的歷史數(shù)據(jù),采用大數(shù)據(jù)手段對數(shù)據(jù)進行分析處理能夠最大限度利用數(shù)據(jù)的價值.如果采用API接口的方式從海量平臺獲取數(shù)據(jù)將會增加程序的復(fù)雜度和開發(fā)難度,而本文的SQL引擎可以讓大數(shù)據(jù)平臺通過SQL的方式訪問海量平臺數(shù)據(jù),降低了開發(fā)難度.
為了驗證功能,進行了如下的實驗.實驗中海量平臺中實時庫存儲了9000萬測點,每個測點均有兩年左右歷史數(shù)據(jù),總數(shù)據(jù)量超過5 TB.
圖6為查詢兩個測點1個小時內(nèi)數(shù)據(jù),測點數(shù)據(jù)頻率為15分鐘,結(jié)果如圖所示.從圖中可以看出SQL語句能夠完整的獲取所需的數(shù)據(jù),并且耗時0.08秒,在功能和性能方面均有很強的實用價值.
圖6 直接獲取海量平臺1個小時測點數(shù)據(jù)
圖7為查詢兩個測點1個月內(nèi)數(shù)據(jù),測點與圖6相同,結(jié)果如圖所示.當(dāng)數(shù)據(jù)量很大時,可通過異步輪循的方式獲取實時數(shù)據(jù).
圖7 直接獲取海量平臺一個月測點數(shù)據(jù)
通常,為了挖掘數(shù)據(jù)價值,需要將海量平臺實時數(shù)據(jù)與關(guān)系數(shù)據(jù)庫中電網(wǎng)檔案模型數(shù)據(jù)相結(jié)合.測試中,SQL引擎需要從海量平臺關(guān)系數(shù)據(jù)庫獲取電網(wǎng)檔案數(shù)據(jù),然后再從海量平臺中實時數(shù)據(jù)庫獲取量測數(shù)據(jù).
如圖8為從關(guān)系庫獲取測點信息后,再從海量平臺實時庫獲取數(shù)據(jù).圖中SQL語句執(zhí)行流程為,SQL引擎將查詢語句提交到另一個關(guān)系庫獲取測點信息后,將測點信息傳入SQL引擎,通過SQL引擎獲取海量平臺中實時數(shù)據(jù).圖8中SQ語句獲取的數(shù)據(jù)與圖6一致.
圖8 從關(guān)系庫中獲取測點信息后再從海量平臺獲取1個小時測點數(shù)據(jù)
圖9為獲取1個月數(shù)據(jù),數(shù)據(jù)與圖7一致,也可通過輪循的方式獲取SQL結(jié)果集數(shù)據(jù).
圖9 從關(guān)系庫中獲取測點信息后再從海量平臺獲取1個月測點數(shù)據(jù)
通過以上測試可以說明本文的SQL引擎在功能和性能上都滿足文中提出的通過SQL方式獲取海量平臺數(shù)據(jù)并提供給大數(shù)據(jù)平臺使用的要求.
針對電網(wǎng)運用中,大數(shù)據(jù)服務(wù)平臺訪問海量平臺中數(shù)據(jù)的問題,本文設(shè)計了基于PostgreSQL的訪問方案.設(shè)計了大數(shù)據(jù)接口模塊的整體架構(gòu),詳細給出了海量平臺FDW模塊的設(shè)計思路與主要流程.采用隨機抽樣的方式估算外部值表的大小,結(jié)合本系統(tǒng)的查詢需求,對SQL語句進行補充改造以及語義分析.利用本文的SQL引擎,上層Spark等大數(shù)據(jù)工具可以SQL的方式成功訪問底層海量平臺的數(shù)據(jù).目前,SQL引擎已集成到南方電網(wǎng)海量準(zhǔn)實時數(shù)據(jù)服務(wù)平臺中,大數(shù)據(jù)應(yīng)用可通過SQL引擎訪問海量平臺底層實時數(shù)據(jù),極大的提高了數(shù)據(jù)資源的利用效率.