李 鋼,茅海泉
(南瑞集團有限公司(國網電力科學研究院有限公司),南京 211000)
(江蘇瑞中數據股份有限公司,南京 210012)
在電網系統中產生的準實時數據[1],可以被應用在調度、在線監測、計量等多種場景中.海量準實時數據服務平臺(以下簡稱海量平臺)是南方電網公司面向數據資源統一管理及針對實時數據管理的有力支撐平臺,可以對生產運行過程中各業務應用形成的實時歷史數據進行存儲、集中、整合、共享和分析,同時提供了標準統一的NOSQL訪問方式.
隨著電網規模的不斷擴大、信息系統的不斷升級擴展,準實時數據呈現海量的特點,具有明顯的大數據[2]特征.Spark[3]、HBase[4]等大數據服務平臺是目前流行的大數據解決方案,得到廣泛的應用.大數據服務平臺可以運用到電網系統中,更好的解決海量準實時數據的存儲、計算、分析等問題,具有很高的實用價值.大數據平臺可以通過JDBC與外部數據源進行連接,獲取電網檔案、模型等關系數據.而海量準實時數據服務平臺提供統一訪問接口UAPI不支持SQL查詢.如何將海量平臺中非結構化的量測數據與模型、檔案等關系數據通過統一SQL訪問引擎結合起來,成為運用大數據服務平臺的關鍵問題.
本文采用分層的策略,在上層大數據平臺與底層海量平臺間設計實現專門的SQL引擎.大數據平臺通過該引擎,運用SQL的方式訪問海量平臺中的數據.SQL引擎基于PostgreSQL設計實現,能解析大數據層的SQL語句并通過UAPI獲取海量平臺數據.現場測試結果驗證了該接口的有效性.
海量平臺中,非結構化數據主要存儲在實時數據庫中.目前國產的實時數據庫僅支持簡單的SQL查詢,無法支持復雜SQL的查詢,如與結構化數據結合的嵌套查詢或者join查詢等.因此,需要開發專用的SQL引擎來實現結構化數據與非結構化數據的聯合查詢,為大數據應用提供數據.基于PostgreSQL的SQL引擎是一種很有效的解決方案.
PostgreSQL是由加州大學伯克利分校[5,6]開發的開源數據庫系統,可以運行在Windows、Linux等多種平臺上.PostgreSQL是世界頂級關系數據庫之一,被廣泛運用在醫療、天文、商業等領域[7].PostgreSQL的主要技術特點包括:
1)標準通用.PostgreSQL基于廣泛應用的關系數據模型,遵循SQL國際標準.PostgreSQL為應用開發提供了符合標準的 ODBC3.0、JDBC3.0、OLEDB 2.7和嵌入式 SQL 接口.PostgreSQL經過大量實際應用的磨合與驗證,已成為標準、通用、安全、穩定、實用、高效的數據存儲與管理平臺.
2)海量存儲.PostgreSQL結合結構化查詢語言的操作能力和過程化語言的數據處理能力,可以有效地支持大規模數據存儲與存取,如TB級的數據庫的表空間、GB級的 BLOB 二進制大對象和 CLOB 文本大對象等,并通過各種約束保證數據的完整性和安全性.
3)Postgres_fdw.Postgres_fdw為PostgreSQL數據庫的外部數據封裝器,可以用來訪問存儲在數據庫外的數據.Postgres_fdw支持支持標準的SQL select語句,不支持insert,update等語句,通過Postgres_fdw,可采用統一的SQL訪問不同數據源的數據.
4)訪問高效.PostgreSQL采用c語言編寫,運用多進程模型,支持高并發訪問.將結果存儲在內存中,有效避開無用的磁盤讀寫,具有高效訪問的特點.
基于以上技術優勢,本文采用PostgreSQL來設計統一SQL引擎.
統一訪問接口(UAPI)是海量平臺對外提供的一套實時數據訪問接口,UAPI不支持SQL訪問.UAPI屏蔽了底層數據庫的具體實現細節及差異,對外提供統一的訪問接口為上層應用服務,對用戶來說是只有一個邏輯實時數據庫,從而實現了透明性以及分布式訪問.
實時數據庫統一訪問接口的實現以標準C/C++語言為編程語言并充分考慮接口的跨平臺性,接口至少支持Windows、Linux等平臺.
在電網系統中運用大數據存儲、分析工具,需要實現將底層海量平臺的數據導入到大數據平臺.大數據平臺通過JDBC接口連接外部數據源,而海量平臺已實現UAPI供外部調用.本文設計實現了基于PostgreSQL的SQL引擎,實現在大數據端通過SQL的方式訪問、抽取海量平臺實時數據.本文訪問引擎實現的主要功能包括:
不包括where條件的查詢.用于查詢所有測點的信息.
帶where條件的測點查詢.查詢符合特定條件的測點信息.此處的條件包括測點標識和測點名.
原始值、斷面、實時值、差值[8]查詢.查詢測點不同類型的值信息.
模糊查詢.便于查詢符合特定條件的相關測點集信息.
帶子查詢的where條件查詢.可以在查詢語句中嵌套子查詢,方便更深層次的應用需求.
指定字段的查詢.用于查詢測點的部分信息.
大數據平臺與海量平臺間通過本文的訪問插件進行連接.具體架構如圖1所示.

圖1 整體架構圖
如圖1,整體架構分為三層,分別是:
接口層: 接口層是大數據平臺的管理接口,主要部署SparkSQL[9].SparkSQL支持在Java,Scala,Python和R等高級語言中使用標準的SQL語句在Spark中查詢結構化數據.大數據分析應用調用SparkSQL接口實現對海量準實時數據服務平臺的數據查詢和分析計算.
大數據平臺層: 大數據平臺是電網系統中大數據工具的部署層,主要涵蓋Spark、HDFS[10]和HBase.Spark負責準實時數據的計算分析,HDFS和HBase解決實時歷史數據的存儲問題.
海量平臺層: 海量平臺層是目前電網系統中部署的實時數據管理平臺,負責對關系數據庫、實時數據庫等數據源的統一管理.在底層的數據源上是本文重點設計實現的SQL解析引擎.大數據訪問接口通過JDBC與大數據平臺連接,與底層的海量平臺通過UAPI連接.整體上,海量平臺作為大數據平臺的外部數據源,通過本文的訪問插件為上層提供數據支撐.
本文基于PostgreSQL的FDW(Foreign Data Wrapper)框架,設計海量平臺大數據訪問接口.本接口對外支持標準JDBC訪問方式.海量準實時數據服務平臺大數據接口模塊架構圖如圖2.

圖2 海量平臺大數據接口模塊架構圖
海量準實時數據服務平臺大數據接口模塊由三部分組成:
1)標準JDBC接口: 基于PostgreSQL對外提供的JDBC接口.用于與上層的Spark、HBase等連接.
2)PostgreSQL插件: 把PostgreSQL數據庫作為海量平臺大數據接口的一個功能插件.此處主要利用PostgreSQL的外部表訪問功能以及PostgreSQL對SQL語句的初步處理.
3)海量平臺FDW模塊: 基于PostgreSQL的FDW模塊,實現對海量平臺外部數據源的訪問.
整個大數據接口模塊中FDW模塊是本文的核心.FDW模塊位于接口的底層,負責連接PostgreSQL與海量平臺.FDW模塊將系統上層大數據部分傳入的SQL語句具體解析后調用相關的UAPI函數以實現準實時數據的傳輸.
海量平臺SQL引擎位于海量平臺大數據接口的底層,基于PostgreSQL的FDW模塊設計實現.整體的設計思路是將海量準實時數據服務平臺中的數據抽象成PostgreSQL的外部表以支持訪問.
電網應用中的準實時數據主要包括測點信息和測點值信息,海量平臺FDW模塊相應的映射為PostgreSQL的外部點表(upoint)和外部值表(uvalue).外部表的字段與實時數據中包含的信息相對應,例如外部值表中包含了測點標識、時間戳、質量位、值等字段.
基于上述思路,設計海量平臺FDW模塊的流程圖,如圖3所示.
海量平臺FDW模塊的主要實現流程包括:
連接海量準實時數據服務平臺.與海量平臺建立連接是進行數據傳輸的第一步.

圖3 海量平臺FDW模塊實現流程圖
估算外部表大小.估算映射的外部表的大小,為后面查詢做準備.
創建外部表查詢訪問路徑和掃描計劃節點.根據外部調用的IP地址是否是本地,設置不同的權重參數;創建訪問路徑.
查詢初始化.主要是解析SQL語句.PostgreSQL對SQL語句進行了簡單的分詞處理,在FDW模塊中還需進一步分析SQL的語義信息,特別是SQL語句中where條件的處理.
執行查詢并返回結果集.根據解析的SQL語句,調用對應的UAPI函數,將結果集組織成PostgreSQL中的記錄格式返回.
海量平臺SQL引擎的各功能點協調有序處理,能保證上層的SQL查詢正確解析;在映射成外部表的基礎上,調用相關UAPI函數,順利完成訪問任務.
在查詢外部表獲得具體的字段信息前,需要對外部表進行大小估算,以生成更優的訪問路徑.本文中外部表包括外部點表和外部值表,分別設計了不同的大小估算方案.
外部點表大小估算: 首先查詢出總共的點數,然后乘以每個點結構所占的大小即可得整體點表的大小.
外部值表大小估算方案較復雜,具體流程如圖4所示.
外部值表大小估算: 如圖4,在海量平臺中,每個測點包含的值的個數不等,不能簡單的根據單個測點值的個數乘以測點總數來估算.而海量平臺中測點數在千萬級別,采用逐個測點查詢累加的方式會嚴重損害效率.本文采用隨機抽樣的方式,抽取總點數的二十分之一,計算此部分的測點值總個數,最后乘以比例得到整體的估計值.

圖4 外部值表大小估算方案示意圖
SQL語句解析是查詢過程中的重要一環.海量平臺FDW模塊在PostgreSQL詞法分析的基礎上,結合本系統的查詢要求,進行SQL語句的補充改造與語義解析,方便查詢時對應到具體的UAPI函數.SQL語句解析的整體框架如圖5所示.

圖5 SQL語句解析框架圖
SQL語句解析主要包括以下解析過程:
根據select后的字段,確定最終返回結果的內容項.如“select name,tagtype,compress”表示需要返回測點的名稱、測點類型以及是否壓縮等信息.
根據from后的字段,確定查詢的是點信息或者是值信息.如“from upoint”表示查詢的是點信息,而“from uvalue”表示返回的是值信息,具體是何種值還需進一步判斷.
解析Where后的信息,獲得UAPI函數調用時的參數.按照變量、常量、子查詢、關系操作符、bool值的分類方法,對每個分詞進行處理.
變量確定給出的信息類型,常量確定信息的具體值.對于id以范圍給出的(between A and B等形式),拆封成單個具體數值.涉及時間的,轉換成海量平臺所用時區的時間.如“where id between 100 and 135” id是變量,100和135是常量,id區間根據UAPI的調用規則轉換成100,101,102,…,135的形式.
對于包含子查詢的,先執行子查詢并將結果傳遞給父查詢.涉及關系操作符和bool值的,需要將兩側的信息分別遞歸處理.如“where id=100 or id=109”‘or’是bool值,需要將兩側信息‘id=100’和‘id=109’分別遞歸到where子句層繼續處理.
增加mode和step字段.根據mode字段的值區分查詢測點值的具體形式(實時值、插值、斷面和原始值).對于查詢差值的,根據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’時間段內的差值信息,查詢步長為1000 ms.
創建外部表,執行create foreign table語句,為每個需要訪問的遠程表創建外部表.在本系統中就是創建外部點表和外部值表.
正確執行上述步驟后,大數據訪問插件即安裝完成.在大數據端可以通過SQL語句訪問底層的實時數據了.
為了驗證SQL引擎功能的正確性,基于海量平臺進行了相關的測試.
測試中,選用的海量平臺中關系庫表有3000萬條數據[10].
海量平臺存儲了大量有價值的歷史數據,采用大數據手段對數據進行分析處理能夠最大限度利用數據的價值.如果采用API接口的方式從海量平臺獲取數據將會增加程序的復雜度和開發難度,而本文的SQL引擎可以讓大數據平臺通過SQL的方式訪問海量平臺數據,降低了開發難度.
為了驗證功能,進行了如下的實驗.實驗中海量平臺中實時庫存儲了9000萬測點,每個測點均有兩年左右歷史數據,總數據量超過5 TB.
圖6為查詢兩個測點1個小時內數據,測點數據頻率為15分鐘,結果如圖所示.從圖中可以看出SQL語句能夠完整的獲取所需的數據,并且耗時0.08秒,在功能和性能方面均有很強的實用價值.

圖6 直接獲取海量平臺1個小時測點數據
圖7為查詢兩個測點1個月內數據,測點與圖6相同,結果如圖所示.當數據量很大時,可通過異步輪循的方式獲取實時數據.

圖7 直接獲取海量平臺一個月測點數據
通常,為了挖掘數據價值,需要將海量平臺實時數據與關系數據庫中電網檔案模型數據相結合.測試中,SQL引擎需要從海量平臺關系數據庫獲取電網檔案數據,然后再從海量平臺中實時數據庫獲取量測數據.
如圖8為從關系庫獲取測點信息后,再從海量平臺實時庫獲取數據.圖中SQL語句執行流程為,SQL引擎將查詢語句提交到另一個關系庫獲取測點信息后,將測點信息傳入SQL引擎,通過SQL引擎獲取海量平臺中實時數據.圖8中SQ語句獲取的數據與圖6一致.

圖8 從關系庫中獲取測點信息后再從海量平臺獲取1個小時測點數據
圖9為獲取1個月數據,數據與圖7一致,也可通過輪循的方式獲取SQL結果集數據.

圖9 從關系庫中獲取測點信息后再從海量平臺獲取1個月測點數據
通過以上測試可以說明本文的SQL引擎在功能和性能上都滿足文中提出的通過SQL方式獲取海量平臺數據并提供給大數據平臺使用的要求.
針對電網運用中,大數據服務平臺訪問海量平臺中數據的問題,本文設計了基于PostgreSQL的訪問方案.設計了大數據接口模塊的整體架構,詳細給出了海量平臺FDW模塊的設計思路與主要流程.采用隨機抽樣的方式估算外部值表的大小,結合本系統的查詢需求,對SQL語句進行補充改造以及語義分析.利用本文的SQL引擎,上層Spark等大數據工具可以SQL的方式成功訪問底層海量平臺的數據.目前,SQL引擎已集成到南方電網海量準實時數據服務平臺中,大數據應用可通過SQL引擎訪問海量平臺底層實時數據,極大的提高了數據資源的利用效率.