練金棟,陳 志,岳文靜,趙 培,3,呂偉初,3
(1.南京郵電大學 計算機學院;2.南京郵電大學 通信與信息工程學院,江蘇 南京 210003;3.金篆信科有限責任公司,江蘇 南京 210012)
隨著數據量的爆發式增長,傳統的單一數據庫模式愈發難以滿足存儲和查詢的實時性要求。數據結構呈現多樣化趨勢,多種存儲類型的數據庫并行交互[1-2],各行業內部出現不同部門存在數據壁壘、數據共享消耗大量資源、數據流轉和融合處理成本上升、數據一致性難以保證等問題[3]。為了滿足各行各業對數據應用的需求,企業開始根據自身業務特點,采用多種數據庫產品管理業務數據,形成了不同技術解決不同場景應用問題的局面[4]:企業會以Oracle、MySQL、PostgreSQL 等多個主流數據庫管理數據;各部門的數據會以CSV、XML、JSON 等不同文件類型分別進行存儲;各類實時業務會采用HBase、MongoDB、Neo4J 等數據庫進行數據處理與分析。研究表明[5],每個企業應用程序至少都涉及兩到三種不同類型的查詢系統,許多現實的分析業務也提出了便捷、高效地執行跨平臺查詢的需求。針對這一情形,研究人員開展了大量針對多源異構數據庫的跨平臺、統一操作技術的研究[6-7]。
然而,與數據庫系統的快速發展相對的,已有的異構數據庫集成操作在易用性、統一性與高效性方面都存在一定的不足[8-10]。首先,現有工作尚未提供一個適用于跨平臺查詢的統一的SQL 查詢語言,易用性不高;其次,由于異構數據庫不同的特性和各異的語法規則,數據庫之間的相互訪問需要通過編寫數據轉換接口來實現,學習成本高且工作量大,擴展性不足。此外,現有工作大多只能針對單一的跨平臺SQL 査詢進行優化,可能嚴重影響跨平臺查詢性能。
為了解決以上問題,本文開發了一套高效、靈活且具有跨平臺特性的多源SQL 解析轉換方案。該方案設計了一種能描述異構數據庫執行邏輯的中間表示模型,通過該模型來隱藏底層庫的差異性,從而實現對異構數據庫的統一解析建模和映射轉換,滿足多種數據集中存儲、查詢和修改的業務需求,提高數據處理效率和靈活性。
SQL 和NoSQL 數據庫都有著各自的適用場景,并能滿足特定的數據需求與應用目標,因此將多種SQL 與NoSQL數據庫進行集成,實現異構數據庫的統一管理和互操作,可以讓不同數據庫系統在功能方面進行有機結合,發揮各自的優勢,從而利于提升數據處理效率,靈活應對各種類型數據的查詢需求[11]。
目前的研究成果主要集中在SQL 與NoSQL 的集成融合系統以及支持數據相互訪問的標準化API 上。文獻[12]通過將key-value 數據轉換合并到關系模型,實現利用PostgreSQL 對MongoDB 進行操作,證明了在關系型和NoSQL 數據存儲上集成統一操作的可能性;文獻[13]提出基于SQL 模型的映射算法,通過SQL 查詢擴充來實現每個SPARQL 代數運算符,并生成高效的SQL 查詢;文獻[14-16]通過設計模式映射和查詢映射方法,實現了關系型數據庫與RDF 平臺的互操作。但此類研究只簡單堆積了少數SQL 和NoSQL 數據庫,僅適用于涉及兩三類不同數據庫的小型業務,不具備通用性。另一些研究進一步嘗試設計統一適配器的方式,通過向統一數據中間模型動態提供適配數據,實現異構數據庫的SQL 統一查詢。文獻[17]提出一種為每種SQL 語句定制正則表達式的方法解析SQL,并通過擴展XQuery 實現對MongoDB 數據庫的操作;文獻[18-20]通過將關系表、鍵值對、CSV 文件、JSON 文件等結構化與半結構化數據轉換為臨時關系表結構,以單一數據庫語法操作實現多數據源的統一查詢。此類方法的局限性在于要求在異構數據庫之間設計數據轉換接口,以實現相互訪問,工作量大,擴展性很差。
本文對上述方案的設計思想和方法進行參考與總結,設計了一套通用的異構數據庫解析轉換方案,通過設計統一中間表示模型來隱藏異構數據庫在查詢語言和數據格式上的差異,實現多種關系型和NoSQL 數據庫的統一解析與轉換,生成統一的邏輯查詢計劃實現底層庫的操作請求,同時保證了較好的可擴展性。
由于Oracle、MySQL、DB2 等基于ANSI-SQL 標準開發的關系型數據庫仍被廣泛應用。本文采用以SQL 語法為基礎、引入多種NoSQL 語法模型的模式設計異構數據庫的中間表示模型。該模式降低了數據模型之間的開發和維護成本,并為滿足特定業務需求提供了更強的靈活性。
由于不同數據庫系統的數據存儲模型不同,在數據命名、數據類型、數據結構方面存在差異[21-22],需要設計不同語法模型之間的轉換策略。如圖1(a)所示的傳統多對多轉換模式,兩個異構數據庫之間直接進行數據轉換,轉換效率高,但n 個異構數據庫節點的雙向操作必須編寫n*(n-1)個數據轉換器。如果新增一個異構數據庫類型,則需要開發2n 個轉換器,導致開發維護成本高、可擴展性差。

Fig.1 Grammar conversion mode圖1 語法轉換模式
本文采取圖1(b)所示的中介轉換模式,即通過設計一種中間模型,為所有的數據庫指令提供統一的元數據描述格式,并通過轉換器實現從源庫數據轉換為中間模型、再由中間模型轉換為目標庫數據的間接轉換模式。該方案僅需編寫2n 種轉換器,當增加、修改一個數據庫存儲模型時,只需編寫新數據庫模型與通用模型的語法轉換器,其它同步節點的數據轉換模塊保持不變。該模式屏蔽了底層數據庫之間的差異,極大地降低了開發難度,并考慮了一定的擴展性。
中間表示模型在解析SQL 語句對數據集合的計算操作后,以結構化形式描述SQL 各個子句語法塊。模型參考文獻[23-25]的設計框架,以實體(Entity)作為對所有SQL語法塊的統一描述,并將部分實體進一步劃分為語句(Stmt)和表達式(Expr)。即:
Stmt 實體存儲SQL 語句執行計劃的基本步驟,Expr 實體存儲執行計劃的具體數據,其他實體負責對Stmt 和Expr作進一步描述。統一的中間表示模型的形式化表示如下:
其中,Type 表示實體類型,Stmt 實體類型包括INSERT、SELECT、CREATE_TABLE,Expr 實體類型包括Numeric、Literal、Logical 等;Field 表示一系列實體集合,即當前實體的所有子句類;Attribute 表示實體內部屬性,即SQL請求的元數據信息;實體關系Relation∈(Entity×Entity)用于描述實體間的語義關聯,包括字符常量與數據表(Table)、數值與數據結構(Datatype);Map 表示此實體的映射轉換方法。
以查詢語句的From 子句為例,在標準 SQL 語句中,From 子句既可以由單個引用表實體組成,又可以由多個引用表實體通過各種形式的連接(Join)構成:
其中,tableSource 實體用于描述引用表,即參與數據查詢的關系表結構,按連接關系分為tableSourceL和tableSourceR。joinType 是一個枚舉(Enum)屬性,代表Join連接操作類型,包括INNER_JOIN、LEFT_JOIN、RIGHT_JOIN 等。condition 是Expr 實體的子類,用于描述SQL 語句的可嵌套邏輯關系式,在fromClause 實體中用于指定tableSourceL和tableSourceR的連接條件。其形式化表示為:
其中,logicalExpr 和comparisonExpr 分別表示可嵌套的邏輯表達式與關系表達式,在SELECT、UPDATE、DELETE等操作中指定數據篩選條件,通過運算符優先級進行劃分。一個logicalExpr 可以由一個comparisonExpr 組成,也可以由若干可嵌套邏輯表達式(nestedLogicalExpr)和邏輯運算符號(AND、OR 和NOT)組合構成,以篩選出符合指定邏輯規則的數據行。logicalExpr 的形式化表示如下:
其中,comparisonExpr 用于根據特定條件比較兩個值或列之間的大小關系以篩選數據。形式表達式如下:
其中,compOp 是關系運算符(如=、<、>、<=、!=等)的集合,表示值或列的比較方式;unaryExpr 實體用于表示計算表達式以及對象名、變量、常量等,是SQL 標準語句中的基本參數。其形式化表示如下:
以上實體構成了Expr 的形式化表示,其中一元表達式的value 代表整數、浮點數、字符串、標識符等,用Java 包裝類型進行存儲;unaryOp 是正負號、引號等常規符號的集合;dataType 表示literal存儲數據的數據類型。
面向多源異構語法的統一SQL 解析轉換器參照傳統數據庫的編譯流程,將解析與轉換功能劃分為語法解析器、語義分析器、語法重構器、查詢優化器等組件,執行流程如圖2所示。首先根據語法文件生成SQL 語法的詞法和語法分析器,組成語法解析器;然后將SQL 語句輸入對應的語法解析器,生成抽象語法樹(Abstract Syntax Tree,AST);接下來使用語義分析器遍歷訪問抽象語法樹,提取特征信息,封裝為中間表示模型并進行語義分析;語法重寫器根據前臺指定的目標庫類型,選取相應轉化策略對中間模型進行映射,使其轉換為能在目標平臺執行的邏輯執行計劃;最后,執行優化器可以對邏輯執行計劃作進一步優化處理,以提高可執行性。

Fig.2 SQL parsing and conversion process圖2 SQL解析轉換流程
語法解析器(Syntax Parser)由ANTLR 工具生成的詞法分析器(Lexer)和語法分析器(Parser)組成,負責在語法規則的支持下,經過詞法解析和語法解析將查詢語句編譯成AST 結構。以SQL 語法為例[26]:詞法分析器負責分析詞法結果,即通過拆解SQL 語句將輸入的字符序列分解成詞法符號(token)序列。其中,token 是語法的基本詞匯符號,可分為5 種類型:①保留字(keyword)。由固定字符序列組成,如select、table、case 等;②標識符(identifier)。如常量名、表名、屬性名;③文字常量(literal)。包括25、4.14、4e3等數字常量,以及“abc”“cid”字符串;④運算符(operator)。常用的包括算術運算符(+-*/)、關系運算符(<,>,<=,!=)和邏輯運算符(NOT、AND、OR);⑤分隔符(separator)。如小括號、中括號、逗號等,負責對標識符進行規范。語法分析器則通過檢查token 的序列結構是否符合語法規則,判斷語句是否合法,并把token 按照語法規則進行模式匹配,組裝成AST 結構。
語義分析是編譯過程中的一個邏輯階段,負責收集抽象語法樹標識符的屬性信息并與節點綁定,審查SQL 查詢請求有無語義錯誤,例如庫表、列名是否存在,列的數據類型是否正確,為邏輯計劃樹生成收集類型信息。
語義分析器(Semantic Analyzer)通過ANTLR 提供Visitor訪問模式按深度優先順序遍歷語法分析樹,通過顯式的方法調用來獲取子節點信息,生成邏輯執行樹結構。具體算法如下:
算法1語義分析算法
算法1以深度優先、自底向上的順序對AST 進行遍歷,將語法樹節點與元數據綁定,引入2.2 節建立的中間表示模型,同時結合上下文進行語義分析。對于整數、字符串及復合表達式等Expr 實體,算法按類型判斷參數類型是否匹配、邏輯是否有歧義、是否超出變量范圍等,接著按照具體值域類型生成繼承表達式類;對于增刪改查等Stmt 實體及其內部元素,算法先判斷是否存在重復聲明屬性、形參與實參不匹配、屬性不存在等語義錯誤,再根據具體SQL語句類型和子句類型封裝語法塊的語義。最終邏輯執行樹能完整描述SQL 的邏輯執行步驟。
以查詢請求“SELECT * FROM people WHERE status="A" ORDER BY user_id DESC”為例,劃分SQL 各語法塊并通過分析可知:查詢實體為people 表,以status="A"為篩選條件獲取實體所有屬性,并將結果集根據user_id 列遞減排序。算法1 生成的中間表示對應的JSON 格式化描述如下:
在語義分析與實體封裝過程中,模塊判斷people 表是否存在,以及是否存在status、user_id 等表屬性、status 屬性是否為varchar 類型數據等。此外還會檢查user_id 是否為people 表索引,若是,則在Query 語義樹中標記其索引名為“user_id”以及對應的索引類型。
語法重寫器(Syntax Rewriter)負責接收語義分析器生成的邏輯執行樹,若目標數據庫為關系型數據庫,則可通過transform 轉換策略將中間表示內部屬性、變量進行修改,實現源實體entitysrc到目標實體entitytarget的轉換。以Oracle 到MySQL 的轉換為例,部分轉換策略如表1所示。
若目標數據庫是NoSQL 類型,則將中間表示轉換為對應的NoSQL 語法。SQL 與NoSQL 的部分對象映射關系如表2 所示。關系型數據庫的表、列、屬性和數據對象分別與NoSQL 數據庫MongoDB 的集合、文檔、字段、值等數據結構對應。
在分析器生成SQL 的邏輯查詢樹后,通過此映射關系將SQL 數據一一轉換為NoSQL 形式,以實現SQL 邏輯執行樹的重構。以MongoDB 為目標對象,其轉換算法如下:
算法2模型轉換算法
若目標數據庫是關系型,則調用查詢優化器(Query Optimizer)對目標SQL 請求進行優化。查詢優化器采用基于規則的優化(RBO)方式定義一系列優化規則,包括列剪裁、最大最小消除、投影消除、謂詞下推、Join 消除等,優化規則與表1 原理一致。優化器搜索過程可視為根據指定的優先順序循環判斷SQL 各語塊是否匹配優化格式(Pattern),若符合則按照優化規則(Rule)對SQL 語句進行優化,并重新進入循環,直到沒有可以匹配的語塊,從而完成優化。
以“獲得滿分成績的學生查詢”為例,常用的SQL 寫法為:SELECT * FROM Student t,Grade g WHERE t.S_id=g.S_id AND g.score=100。該Select語句對應的關系代數為:
根據代數式可知,語句在執行時數據庫會先全表掃描全部的Student 學生信息表和Grade 學生成績表,然后才根據where 條件進行篩選,因而提高了查詢計算量。這種情況可以通過謂詞下推,將過濾條件表達式(如=、!=、like、in、between 等)盡量靠近待過濾的數據源(Student 表和Grade 表),即先將通過過濾條件“grade=100”篩選Grade 表中的數據,再進行連接操作,以達到優先過濾無用數據、提升SQL 執行效率的目的。對應關系代數為:
轉換成對應語句為:SELECT * FROM Student t1 RIGHT JOIN(SELECT * FROM Grade WHERE grade=100 )t2 ON t1.S_id=t2.S_id。轉換前和轉換后的關系表達樹如圖3所示。

Fig.3 Query optimization -predicate pushdown圖3 查詢優化—謂詞下推
如圖3 所示,在數據庫執行查詢操作時,邏輯執行計劃根據關系表達樹中的操作符逐步向上計算,直到根節點(整個表達式)的計算完成。因此,通過謂詞下推,數據庫在內查詢時就先過濾了Grade 表中的大部分無用數據,極大地減少了臨時表的空間開銷,提高了查詢效率。
為驗證面向多源異構數據庫的SQL 解析轉換器在實際開發環境中的應用,本文基于方案實現了一個多源異構數據庫的統一操作系統,旨在檢驗解析轉換器在異構數據庫間跨平臺訪問的可靠性、正確性和高效性。功能測試主要驗證查詢系統在多源異構、跨平臺環境下數據庫對基本操作的支持度,以及核心查詢業務的可靠性,性能測試主要驗證解析轉換器基本增刪改查操作的性能。
操作系統以Java 編程平臺作為運行平臺,分別使用Oracle、MySQL 和MongoDB 存儲關系型和非關系型數據,并基于TPC-H 基準測試數據集進行功能測試和性能測試,實驗中針對不同測試單元對數據集進行相應處理。具體實驗環境參數如表3所示。

Table 3 Environmental configuration table表3 環境配置表
4.2.1 數據類型支持度
為測試本系統對各結構化、半結構化數據的支持度,先導入完整的包含各種類型的測試數據集(所有數據均不包含NULL 和NAN 值)。為維護執行效率,各底層庫隨機導入數據集數據1萬條,再使用簡單的query操作語句對數值型、字符型和時間日期型數據進行查詢與解析,檢驗最終的返回結果是否與映射表相符,以及是否存在非法值或缺失。其中,數據類型映射基于SQLines 技術文檔(Oracle映射至MySQL 類型映射表:http://www.sqlines.com/oracleto-mysql)進行整合,部分映射如表4所示。

Table 4 Data types mapping表4 數據類型映射
經自定義函數對查詢結果進行數據統計和異常值檢驗,最終的實驗結果表明,系統支持對所有已集成數據庫的數據類型進行解析、存儲和映射轉換。
4.2.2 操作類型支持度
本系統已集成的數據庫有Oracle、MySQL 和MongoDB,本節測試其對于SQL 各種操作類型的支持度。實驗涉及的SQL 語句主要面向與具體數據操作相關的環境,所以在實驗論證中只對關系型數據庫的部分DDL 語句和DML 語句,以及NoSQL 的標準CURD 語句進行實驗驗證。實驗分別在Oracle、MySQL 及MongoDB 數據庫創建相應的數據集,并對多源異構數據執行增刪改查操作。實驗結果如表5所示。

Table 5 Support for SQL statement表5 對SQL語句類型支持情況
其中,NoSQL 的CURD 操作對應關系型數據庫的DML語句。MongoDB 的數據存儲類型是BSON 文檔,可以通過insert()、update()、delete()方法動態指定集合(Collection)、文檔(Document)內部field 的數據類型。因此,MongoDB 對數據存儲對象的DDL 操作不納入測試。由表5 可知,解析轉換器支持所有常見關系型數據庫之間的DDL 與DML 互操作,以及關系型與NoSQL 的CURD 互操作。
性能測試通過將系統與官方的mongo-jdbc 插入、刪除、更新和選擇操作的時間開銷進行對比,以評估多源異構解析轉換器的SQL 覆蓋率和各項訪問操作的性能。為有效評估解析轉換器的跨平臺訪問性能,本節引入MongoDB 官方推出的mongo-jdbc 驅動插件,使用SQL 對MongoDB 進行異構訪問,分別讓MongoDB 數據庫、mongo-jdbc和測試系統執行1 000 次INSERT、UPDATE、DELETE 與SELECT 操作,測試結果如表6 所示。其中,每個操作對應的執行時間為執行的平均時間,單位為毫秒(ms)。

Table 6 Comparison of CURD performance testing表6 CURD性能測試結果對比
實驗數據表明,查詢系統在CURD 操作方面的總體性能優于mongo-jdbc。在同等條件下,測試系統執行CURD操作的響應時間較官方工具分別快了13.1 ms、8.8 ms、22.5 ms 與2.3 ms。其中,由于INSERT 操作的平均單次響應時間較短,因此延遲率高,但平均響應時間僅為mongojdbc 的49%。在SELECT 查詢操作上,系統較官方驅動程序平均僅快2.3 ms,沒有明顯優勢,主要由于相較于增刪改操作,查詢樣例涉及嵌套查詢、連接表、過濾條件式等復雜的query 業務,在解析優化和底層執行方面開銷更多,因此平均執行和響應時間更長。
以上結果表明,面向多源異構數據庫的SQL 解析轉換器相較于mongo-jdbc 有著更優異的性能,且其運算成本始終保持在一個固定范圍內,與操作類型無關。實驗結果證明,面向多源異構數據庫的SQL 解析轉換器在功能和性能方面可滿足預期需求,有效實現了對多個異構數據庫的集成操作,且能保證一定的正確性。
本文提出一種滿足跨平臺統一查詢需求的SQL 解析和轉換方法,詳細設計了一系列查詢語言的適配存儲結構和語義一致性轉換及性能優化策略,允許用戶在異構關系數據庫和NoSQL 數據庫上進行準確、可靠的SQL 操作,屏蔽了不同執行平臺間在語法邏輯、底層機制方面的差異,將多個異構數據庫轉換為一個統一的模式,并通過設計測試系統進行功能和性能驗證,證明了解析轉換器的可行性。實驗結果表明,面向多源異構數據庫的SQL 解析和轉換方法在滿足多源異構數據庫跨平臺訪問功能需求的同時,還具有較好性能,且在集成系統的多對多數據訪問環境下具有良好的可擴展性和準確性。
由于條件和時間限制,本文仍有諸多不足,有待進一步研究和改進,主要改進方向有:①增加對更多異構數據庫的適配訪問和操作業務支持。目前跨平臺解析轉換方案僅實現了對Oracle、MySQL 和MongoDB 等若干數據庫的支持,對數據和事務的一致性支持尚不夠全面,難以支持復雜的業務操作;②提升跨平臺解析轉換方案面對真實海量數據處理業務的性能。實驗的測試數據在數據規模和復雜度上與真實業務差距較大,需要將方案置于接近真實海量數據環境中進行測試與改進;③進一步完善跨平臺執行優化模塊。目前優化器主要基于傳統經驗編寫一系列靜態策略以實現查詢優化,在開發和使用效率上具有局限性,可以引入基于代價的優化(CBO)算法,獲得所有等價的重構變換方案,進一步提升查詢性能。