馬志程,袁海峰,谷 洋,劉亞茹,張 孝+
1.國網(wǎng)甘肅省電力公司電力科學(xué)研究院,蘭州 730070
2.數(shù)據(jù)工程與知識工程教育部重點實驗室(中國人民大學(xué)),北京 100872
3.中國人民大學(xué) 信息學(xué)院,北京 100872
近年來,數(shù)據(jù)已經(jīng)滲透到當(dāng)今每一個行業(yè)和業(yè)務(wù)職能領(lǐng)域,成為重要的生產(chǎn)因素。人們對于海量數(shù)據(jù)的挖掘和運用,預(yù)示著新一波生產(chǎn)率增長和消費者盈余浪潮的到來[1]。關(guān)系數(shù)據(jù)庫是數(shù)據(jù)管理中不可或缺的技術(shù),尤其在涉及到用戶、財物等需要精細(xì)管理的應(yīng)用領(lǐng)域時,更是具有不可替代的地位[2]。但是傳統(tǒng)的關(guān)系型數(shù)據(jù)庫在大數(shù)據(jù)背景下存在一些技術(shù)缺陷,尤其是在速度、存儲量以及多樣化結(jié)構(gòu)數(shù)據(jù)的處理問題上存在一些短板。目前的大數(shù)據(jù)應(yīng)用中包含的數(shù)據(jù)類型是多種多樣的,既可以是結(jié)構(gòu)化的關(guān)系數(shù)據(jù)與圖數(shù)據(jù)等,還可以是JSON(Javascript object notation)、XML(extensible markup language)等半結(jié)構(gòu)化數(shù)據(jù),甚至是網(wǎng)頁、視頻等非結(jié)構(gòu)化的數(shù)據(jù)[3]。數(shù)據(jù)模型是一個數(shù)據(jù)管理系統(tǒng)的核心,純關(guān)系模型已經(jīng)無法靈活地管理多種類型的數(shù)據(jù)。其次,在包含大量節(jié)點的集群中,高速處理海量數(shù)據(jù)也是一個難點。再次,在關(guān)系數(shù)據(jù)庫上無法完成對數(shù)據(jù)的復(fù)雜分析[4]。
進(jìn)入大數(shù)據(jù)時代之后,已經(jīng)無法使用某種單一的數(shù)據(jù)庫管理系統(tǒng)來完成所有應(yīng)用的數(shù)據(jù)管理。和關(guān)系數(shù)據(jù)庫不同的是,文檔數(shù)據(jù)庫往往是把某個對象的所有信息全部存儲在一個集合中,并且集合中的每個對象的內(nèi)部結(jié)構(gòu)無需完全相同,這種設(shè)計思想極大地簡化了從外部對象到數(shù)據(jù)庫對象的映射處理[5]。NoSQL(not only structured query language)數(shù)據(jù)庫目前處于百花齊放的狀態(tài),由于存儲模式的不同,也沒有提供統(tǒng)一的查詢語言,也因此導(dǎo)致了NoSQL 數(shù)據(jù)庫沒有統(tǒng)一的數(shù)據(jù)訪問接口[6]。需要一種更加開放的數(shù)據(jù)庫管理系統(tǒng)。將具有豐富多樣的數(shù)據(jù)類型的數(shù)據(jù)在同一個數(shù)據(jù)管理系統(tǒng)中進(jìn)行存儲、組織與管理。這也就意味著單一的數(shù)據(jù)庫引擎必定無法完成數(shù)據(jù)的統(tǒng)一訪問,需要能夠容納與支持多種數(shù)據(jù)模型的處理引擎并存于系統(tǒng)中。在異構(gòu)數(shù)據(jù)的自適應(yīng)存儲前提下(即不同結(jié)構(gòu)的數(shù)據(jù)可能被獨立存儲在不同的數(shù)據(jù)庫中,或者為了更好地服務(wù)于查詢,同樣語義的數(shù)據(jù)被冗余地存儲于不同結(jié)構(gòu)的數(shù)據(jù)庫中),如何基于關(guān)系數(shù)據(jù)庫的架構(gòu)融入NoSQL數(shù)據(jù)庫引擎,怎樣面對用戶定義的操作,如何針對不同引擎的查詢特點來實現(xiàn)跨引擎的查詢以及如何處理大數(shù)據(jù)管理系統(tǒng)中的查詢表達(dá)與查詢優(yōu)化并提高查詢性能,是構(gòu)建能容納和支持多種不同結(jié)構(gòu)數(shù)據(jù)處理引擎并存的大數(shù)據(jù)管理系統(tǒng)需要考慮的重點問題。
基于以上的研究背景,啟動了將關(guān)系型數(shù)據(jù)庫和NoSQL數(shù)據(jù)庫進(jìn)行集成的通用性大數(shù)據(jù)管理平臺DataCloud 項目的研究設(shè)計。本文的研究是Data-Cloud 大數(shù)據(jù)管理平臺的一個子課題。本文研究了關(guān)系型數(shù)據(jù)庫和NoSQL文檔數(shù)據(jù)庫融合的查詢處理技術(shù),實現(xiàn)了一個執(zhí)行引擎ENTIA,將支持結(jié)構(gòu)化數(shù)據(jù)和半結(jié)構(gòu)化數(shù)據(jù)的兩種不同的數(shù)據(jù)庫引擎集成在同一大數(shù)據(jù)管理系統(tǒng)中,提供統(tǒng)一的訪問接口,來完成混合引擎的查詢處理,并基于啟發(fā)式規(guī)則完成部分查詢優(yōu)化功能,為構(gòu)建支持多種數(shù)據(jù)模型的通用性大數(shù)據(jù)管理系統(tǒng)奠定基礎(chǔ)。
此外,本文的研究內(nèi)容也對解決實際工程中的問題,提高開發(fā)效率具有很重要的意義。由于NoSQL數(shù)據(jù)庫采用非規(guī)范統(tǒng)一的存儲方式,即一種數(shù)據(jù)庫只服務(wù)于一種數(shù)據(jù)庫類型,導(dǎo)致截至目前仍然沒有統(tǒng)一的查詢表達(dá)來訪問所有的NoSQL數(shù)據(jù)庫。在實際的項目開發(fā)中,當(dāng)需要同時訪問關(guān)系數(shù)據(jù)庫和NoSQL 數(shù)據(jù)庫時,往往需要程序員針對不同的數(shù)據(jù)庫引擎分別創(chuàng)建連接,用相應(yīng)的數(shù)據(jù)庫引擎定義的查詢語言給出查詢請求,在獲取各個處理引擎返回的查詢結(jié)果之后,再以代碼的方式手工合并各部分結(jié)果從而完成整體的功能需求。這種處理方式不僅要求程序員需要掌握多種數(shù)據(jù)庫的查詢語言,還增加了研發(fā)的工作量,降低了開發(fā)效率。此外,無法充分基于數(shù)據(jù)、查詢與數(shù)據(jù)庫引擎本身的特性來對整體查詢做進(jìn)一步的優(yōu)化。
本文的主要貢獻(xiàn)如下:
(1)系統(tǒng)地介紹了執(zhí)行引擎ENTIA 的整體架構(gòu)與設(shè)計實現(xiàn)。ENTIA包含四大模塊:查詢解析模塊、查詢優(yōu)化模塊、查詢翻譯模塊和查詢執(zhí)行模塊。并具體地闡述了各個模塊的功能與實現(xiàn)原理。
(2)提供了統(tǒng)一的數(shù)據(jù)訪問接口。設(shè)計了全局視圖來屏蔽底層數(shù)據(jù)的結(jié)構(gòu)類型與物理存儲的位置,并基于此定義查詢語言,使得用戶仍然采用熟悉的SQL(structured query language)來完成包含一種或多種存儲引擎、多種數(shù)據(jù)模型的混合查詢,大大提高了開發(fā)效率。
(3)基于啟發(fā)式規(guī)則進(jìn)行查詢優(yōu)化。在數(shù)據(jù)冗余存儲的前提下,將原查詢分解成若干子查詢,進(jìn)而把計算推向合適的存儲引擎,充分利用各數(shù)據(jù)庫引擎的查詢優(yōu)勢,從而提高整體查詢的性能。
(4)進(jìn)行充分的實驗,并對實驗結(jié)果進(jìn)行分析。通過實驗證明:與傳統(tǒng)方案對比,多引擎、多數(shù)據(jù)模型下的混合查詢在保證查詢結(jié)果正確的前提下,不降低查詢性能,證明了方法的正確性;與任一單獨數(shù)據(jù)庫的查詢性能進(jìn)行對比,表明了優(yōu)化方法對數(shù)據(jù)庫性能提升的有效性。
異構(gòu)數(shù)據(jù)庫集成的研究初期是以外部數(shù)據(jù)的管理開始的。Melton 等提出了一種稱為SQL/MED 的架構(gòu)設(shè)計[7]。MED 的含義是Management of External Data。SQL/MED 提供了對SQL 語法的擴展,以及一組用于開發(fā)和管理訪問SQL 數(shù)據(jù)和NoSQL(也稱為外部)數(shù)據(jù)的應(yīng)用程序的例程。SQL/MED 可以分為兩大部分。第一部分稱為包裝接口(wrapper inter-face),提供了可以查看由一個或多個外部服務(wù)器上外部數(shù)據(jù)的功能。外部數(shù)據(jù)可以存儲在文件系統(tǒng)、HTML 格式的網(wǎng)頁、XML 文檔或其他一些專門的存儲庫中[8-9]。SQL/MED 的第二部分稱為數(shù)據(jù)鏈(data-links),它提供了一些工具,使一個SQL Server能夠控制對駐留在一個或多個文件系統(tǒng)中的數(shù)據(jù)的引用完整性、恢復(fù)和授權(quán)的管理。
Tatemura等給出了一個原型系統(tǒng)Partiqle[10],它將SQL引擎集成在基于鍵值存儲NoSQL數(shù)據(jù)庫HBase之上,以達(dá)到支持關(guān)系數(shù)據(jù)庫中的OLTP(on-line transaction process)特性的目的。在這個原型系統(tǒng)中,重點研究了如何將關(guān)系數(shù)據(jù)庫中的事務(wù)引入到HBase 中。Partiqle系統(tǒng)定義了一種“事務(wù)類”的聲明規(guī)范,來約束工作負(fù)載中的事務(wù)。給定一個SPJ(select-project-join)查詢,系統(tǒng)的編譯模塊會基于鍵值存儲的查詢優(yōu)化器之上產(chǎn)生一個新的執(zhí)行計劃。執(zhí)行引擎和事務(wù)管理器會以一種樂觀的并發(fā)控制方式來執(zhí)行此查詢計劃。所謂樂觀的并發(fā)控制方式就是,系統(tǒng)會緩沖寫操作,來提交HBase中的check-and-put的原子操作[10]。
Vila?a 等針對NoSQL 數(shù)據(jù)庫中的查詢需要手工編寫的缺陷[11],在HBase 基礎(chǔ)之上集成了SQL 的引擎。在保留了NoSQL數(shù)據(jù)庫的高可擴展性與模式靈活性的前提下,融入了SQL 查詢,為NoSQL 數(shù)據(jù)庫增加了原來所不能支持的一些操作符,比如join等[12]。文中采用的方法是重寫關(guān)系數(shù)據(jù)庫的內(nèi)部架構(gòu),在保留一部分原來組件的基礎(chǔ)之上,增加了NoSQL 數(shù)據(jù)庫的部分組件。查詢處理器將以SQL表達(dá)的訪問請求進(jìn)行翻譯、編譯和執(zhí)行,同時包括底層存儲的數(shù)據(jù)類型、存儲模式、索引以及各類操作符的一系列轉(zhuǎn)換,最終完成數(shù)據(jù)查詢[13]。該研究中采用了開源、輕量級用Java 編寫的Apache Derby 數(shù)據(jù)庫和HBase 來作為NoSQL數(shù)據(jù)庫[11]。
無論是同構(gòu)數(shù)據(jù)庫的集成還是異構(gòu)數(shù)據(jù)庫的集成,數(shù)據(jù)模式都是非常核心與具有挑戰(zhàn)性的研究工作。Mason等在研究如何集成同構(gòu)數(shù)據(jù)庫時提出了一種基于“注解”的方法來動態(tài)地生成全局語義視圖[14]?!白⒔狻狈椒▽?fù)雜的語義識別任務(wù)轉(zhuǎn)移到局部注釋器而不是全局集成器,從而消除了全局視圖構(gòu)建的瓶頸。這使得集成更加自動化、可擴展和可快速部署。數(shù)據(jù)源管理員使用有意義的名稱(可能使用本體)對架構(gòu)進(jìn)行注釋,并在XML文檔中導(dǎo)出具有注釋的架構(gòu)設(shè)計。系統(tǒng)會加載每個單獨的注釋,匹配注釋中的名稱以生成集成視圖,然后標(biāo)識用于跨數(shù)據(jù)庫連接全局鍵,最終得到一份數(shù)據(jù)模式的全局視圖[15]。
本章將系統(tǒng)闡述基于關(guān)系型數(shù)據(jù)庫PostgreSQL和NoSQL 數(shù)據(jù)庫MongoDB 所實現(xiàn)的執(zhí)行引擎ENTIA 的架構(gòu)設(shè)計,分析各個關(guān)鍵模塊的功能與實現(xiàn)細(xì)節(jié)。并以具體實例介紹如何通過該引擎來完成異構(gòu)數(shù)據(jù)庫的混合查詢。
ENTIA 主要用于解決在集成關(guān)系數(shù)據(jù)庫與NoSQL數(shù)據(jù)庫的系統(tǒng)中的查詢處理問題。該引擎包含查詢解析、查詢優(yōu)化、查詢重寫和查詢執(zhí)行四個模塊,其系統(tǒng)架構(gòu)如圖1所示。
Fig.1 Architecture diagram of ENTIA system圖1 ENTIA系統(tǒng)架構(gòu)圖
從圖1 中可以看到,不同的客戶端應(yīng)用通過ENTIA提供的統(tǒng)一訪問接口來向服務(wù)器發(fā)出查詢請求。查詢解析模塊與元數(shù)據(jù)模塊協(xié)作完成查詢請求的解析工作,其中元數(shù)據(jù)模塊存儲著多源異構(gòu)數(shù)據(jù)庫的數(shù)據(jù)模式的全局視圖,查詢解析后的結(jié)果以Java對象的形式來表示。查詢優(yōu)化模塊基于解析后的結(jié)果與元數(shù)據(jù)信息給出執(zhí)行效率最高的查詢計劃。根據(jù)優(yōu)化器給出的查詢計劃,查詢翻譯模塊會將原本的查詢進(jìn)行翻譯,即以SQL 表達(dá)的查詢請求轉(zhuǎn)換為該查詢計劃中所參與的各個數(shù)據(jù)庫引擎所能識別接受的查詢語言,最終給出與用戶原查詢等價的查詢?nèi)蝿?wù)列表。查詢執(zhí)行模塊負(fù)責(zé)接收所有查詢?nèi)蝿?wù),并給出最終的查詢結(jié)果。查詢執(zhí)行器集成了不同數(shù)據(jù)庫引擎的訪問驅(qū)動,它既可訪問關(guān)系數(shù)據(jù)庫,又可訪問NoSQL數(shù)據(jù)庫。查詢執(zhí)行器將查詢?nèi)蝿?wù)進(jìn)行分發(fā),不同數(shù)據(jù)庫引擎執(zhí)行各自查詢?nèi)蝿?wù),各數(shù)據(jù)庫引擎完成查詢后,將查詢結(jié)果全部返回給查詢執(zhí)行器,查詢執(zhí)行器完成全局的連接工作,得到最終的查詢結(jié)果,返回給客戶端。
從ENTIA 的架構(gòu)中能夠看出,該引擎主要從三方面來實現(xiàn)跨引擎的混合查詢:首先,查詢執(zhí)行模塊向上提供了統(tǒng)一的數(shù)據(jù)訪問接口,從而屏蔽了存儲層數(shù)據(jù)存儲的不一致。一份完整的數(shù)據(jù)既可部分存儲在關(guān)系數(shù)據(jù)庫,部分存儲在NoSQL數(shù)據(jù)庫,也可以不同的結(jié)構(gòu)冗余存儲在多種數(shù)據(jù)庫中。無論采用怎樣的存儲策略,向上的訪問接口是一致的。其次,混合查詢使用全局?jǐn)?shù)據(jù)模式和統(tǒng)一的查詢優(yōu)化器來保證查詢的正確性和性能。再次,向客戶端提供統(tǒng)一的查詢語言,在查詢表達(dá)層做到了統(tǒng)一和規(guī)范。
全局視圖的設(shè)計主要是為了解決底層各個數(shù)據(jù)庫引擎存儲模式之間的差異問題。
全局視圖中,每一個數(shù)據(jù)元素都有兩個名稱:一個是該數(shù)據(jù)元素的“原始名稱”;另一個是該數(shù)據(jù)元素在全局視圖下的“語義名稱”。“語義名稱”并不具有唯一性,不同的數(shù)據(jù)元素可能具有相同的“語義名稱”。針對“表”或者“集合”,全局視圖會給出“語義名稱”“數(shù)據(jù)源”“數(shù)據(jù)庫”“數(shù)據(jù)域”“主鍵”“外鍵”共六個屬性?!皵?shù)據(jù)源”為該表或集合的存儲引擎?!皵?shù)據(jù)庫”為該表或集合所屬的數(shù)據(jù)庫名稱?!皵?shù)據(jù)域”為該表所包含的字段或?qū)傩?。主、外鍵屬性用來完成多表之間的連接操作。針對數(shù)據(jù)庫元素中的“字段”或者“屬性”,全局視圖會給出“字段名稱”“語義名稱”和“數(shù)據(jù)類型”三個屬性。全局視圖由數(shù)據(jù)庫管理員生成,以JSON文件的形式保存在系統(tǒng)中。當(dāng)系統(tǒng)中任意一個數(shù)據(jù)庫引擎的數(shù)據(jù)模式發(fā)生變化時,需要更新JSON 文件來保持全局視圖與各個數(shù)據(jù)庫引擎之間的同步。ENTIA系統(tǒng)中的全局視圖設(shè)計示例如下所示:
本文中的研究內(nèi)容暫時只支持?jǐn)?shù)據(jù)查詢語言(data query language,DQL)[16-17]。由于MongoDB 中沒有數(shù)據(jù)模式的概念,ENTIA 所支持的SQL 是基于全局視圖中的語義名稱來構(gòu)成。其基本語法如下:
SELECT[ALL|DISTINCT]<全局視圖-目標(biāo)列表達(dá)式>[,<全局視圖-目標(biāo)列表達(dá)式>]……
FROM<全局視圖-表名>[,<全局視圖-表名>]……
[WHERE <條件表達(dá)式>]
[GROUP BY<全局視圖-列名1>[HAVING<條件表達(dá)式>]]
[ORDER BY<全局視圖-列名2>[ASC|DESC]]
本節(jié)按照查詢處理的順序來介紹ENTIA對用戶的訪問請求的處理流程。以查詢Q3.1為例:
其中,字段name、stars 存儲在PostgreSQL 中,屬性attribute存儲在MongoDB中。
ENTIA 收到查詢之后,首先會基于JSqlParser 對查詢進(jìn)行解析,生成一個代表該SQL 查詢的Java 對象ParseNode。
針對Q3.1,ENTIA 的查詢優(yōu)化模塊給出的邏輯查詢計劃如圖2所示。
Fig.2 Logical plan query diagram of Q3.1圖2 Q3.1邏輯計劃查詢圖
在跨引擎的混合查詢中,如何將計算任務(wù)合理地分配到每一個數(shù)據(jù)源直接決定了結(jié)果的正確性與查詢效率。本節(jié)中的查詢優(yōu)化的目標(biāo)就是基于優(yōu)化規(guī)則,把數(shù)據(jù)推向合適的計算引擎,將查詢?nèi)蝿?wù)盡量下推到各個數(shù)據(jù)庫引擎,而針對分離后的查詢子任務(wù)的更為具體的查詢計劃則是由各個數(shù)據(jù)庫引擎給出。查詢優(yōu)化的策略是由用戶查詢的特點與數(shù)據(jù)的存儲情況所共同決定的。
在混合存儲引擎系統(tǒng)中,數(shù)據(jù)的存儲情況在字段的粒度上可分為冗余存儲與非冗余存儲兩種情況。非冗余存儲是指,字段被唯一地存儲于眾多數(shù)據(jù)庫引擎當(dāng)中的某一個數(shù)據(jù)庫引擎中,該字段的數(shù)據(jù)僅此一份。冗余存儲是指,字段在至少兩個甚至多個數(shù)據(jù)庫引擎中都有所存儲,該字段擁有多份不同結(jié)構(gòu)類型的數(shù)據(jù),雖然存儲形式不同,但所表達(dá)的語義相同。
用戶的查詢特點是查詢優(yōu)化中優(yōu)化策略的另一決定因素。經(jīng)前期實驗測試:與PostgreSQL 相比,MongoDB在聚合操作與選擇全表掃描策略時的字段投影操作具有明顯的查詢優(yōu)勢,而在表連接的操作上,性能遠(yuǎn)不如PostgreSQL。此外,數(shù)據(jù)查詢語言DQL中,不相關(guān)子查詢是較為具有代表性、更容易解析與判斷的復(fù)雜查詢。因此基于前期的實驗結(jié)論,當(dāng)用戶的查詢中具備上述特點時,ENTIA 可對此類查詢進(jìn)行優(yōu)化。
圖3 是ENTIA 查詢優(yōu)化模塊的工作流程圖。目前ENTIA能夠優(yōu)化的查詢?yōu)榘酆喜僮骰蛘呷頀呙璨僮鞯牟幌嚓P(guān)子查詢。ENTIA根據(jù)查詢解析之后的ParseNode以及數(shù)據(jù)存儲的元信息進(jìn)行判斷:用戶查詢的所有數(shù)據(jù)是否冗余存儲,若非冗余存儲,則進(jìn)一步判斷當(dāng)前查詢是否為跨引擎查詢。若數(shù)據(jù)全部存儲在某一引擎中,顯然該查詢會被完整地在該引擎中完成,若查詢是跨引擎的混合查詢,查詢模塊將分離原查詢中各個操作符,使得各引擎單獨完成分解之后的查詢,并保證各部分查詢之后返回的結(jié)果與用戶的原請求查詢等價。當(dāng)查詢數(shù)據(jù)被冗余存儲在不同結(jié)構(gòu)的數(shù)據(jù)庫引擎中時,需要進(jìn)一步判斷是否為可優(yōu)化的查詢。若不滿足可優(yōu)化規(guī)則,則ENTIA統(tǒng)一將查詢交由PostgreSQL來完成。若滿足優(yōu)化規(guī)則,再根據(jù)查詢中是否包含聚合操作,或者全表掃描操作來選擇對應(yīng)的規(guī)則進(jìn)行優(yōu)化。
4.2.1 聚合操作規(guī)則
規(guī)則1(聚合操作規(guī)則)由于MongoDB 中聚合操作采用管道流水線來處理管道中的一個個功能節(jié)點,大大提高了聚合操作的效率,其性能遠(yuǎn)遠(yuǎn)高于PostgreSQL。因此,聚合操作優(yōu)化規(guī)則是指當(dāng)查詢符合以下形式時:
即,如果整體查詢?yōu)椴幌嚓P(guān)子查詢,并且子查詢中包含聚合操作,那么該查詢會被分解成兩個子任務(wù):子查詢被重寫為MongoDB 查詢,外層查詢?nèi)匀挥蒔ostgreSQL 執(zhí)行,兩個子任務(wù)并行執(zhí)行,兩數(shù)據(jù)庫引擎返回各自查詢結(jié)果,最后連接兩部分查詢結(jié)果得到用戶原查詢的結(jié)果。其中,含有聚合操作的子查詢重寫為MongoDB查詢的方式為:
Fig.3 Query optimization workflow of ENTIA圖3 ENTIA查詢優(yōu)化的工作流程圖
聚合操作優(yōu)化規(guī)則的偽代碼如算法1所示。
算法1聚合操作優(yōu)化規(guī)則
輸入:參數(shù)1,形式為包含聚合操作的不相關(guān)子查詢;參數(shù)2,保存全局視圖的JSON文件的路徑。
輸出:重寫后的PostgreSQL查詢和MongoDB查詢。
4.2.2 全表掃描規(guī)則
經(jīng)過前期的實驗測試,當(dāng)查詢請求的執(zhí)行計劃為全表掃描時,MongoDB 的查詢速度要遠(yuǎn)遠(yuǎn)快于PostgreSQL 的查詢速度。因為在MongoDB 中,當(dāng)數(shù)據(jù)庫啟動時,會將磁盤的數(shù)據(jù)加載到內(nèi)存中,充分利用系統(tǒng)的內(nèi)存資源,磁盤的I/O效率與內(nèi)存的查詢導(dǎo)致兩者查詢速度的差異自然十分明顯。全表掃描優(yōu)化規(guī)則是指,當(dāng)查詢符合以下形式時:
即整體查詢?yōu)椴幌嚓P(guān)子查詢,子查詢的查詢計劃是全表掃描操作時,該查詢可被進(jìn)一步優(yōu)化,原查詢被拆解成兩部分執(zhí)行,子查詢被重寫為MongoDB 的查詢,外層查詢?nèi)匀唤唤oPostgreSQL來執(zhí)行,兩引擎并行執(zhí)行各自的查詢?nèi)蝿?wù),最后將返回的兩部分查詢結(jié)果連接起來完成原來的查詢?nèi)蝿?wù)。其中子查詢被重寫為MongoDB的查詢的形式為:
在MongoDB 中查詢條件是由多個鍵值對的形式來表達(dá)的,將多個查詢條件組合在一起,即完成了“條件1 AND 條件2 OR 條件3”的表達(dá)。鍵為列名、值為1的形式用來表示此列被投影出來,與SQL中的project語義相同。另外,在對當(dāng)前查詢判斷是否符合全表掃描優(yōu)化規(guī)則時,在程序中需要基于EXPLAIN SQL 來獲取該子查詢的查詢計劃,再進(jìn)一步判斷是否由全表掃描操作完成。全表操作優(yōu)化規(guī)則的偽代碼與算法1類似。
5.1.1 實驗環(huán)境
實驗在普通PC 機上進(jìn)行,基本的硬件配置如表1所示。
Table 1 Hardware configuration表1 硬件配置
5.1.2 實驗數(shù)據(jù)集
本實驗所使用的數(shù)據(jù)集是美國最大的點評網(wǎng)站Yelp 所公開的內(nèi)部數(shù)據(jù)集。該數(shù)據(jù)集的內(nèi)容是Yelp所涵蓋的商家數(shù)據(jù)、用戶數(shù)據(jù)和點評數(shù)據(jù)的一個子集。目前Yelp 提供了這個數(shù)據(jù)集的JSON 文件。該數(shù)據(jù)集被廣泛用于自然語言處理和情感分析、數(shù)據(jù)庫、圖像挖掘等領(lǐng)域。本文將該數(shù)據(jù)集的JSON格式數(shù)據(jù)存儲于MongoDB 中,共有business、user 和rev-iew三個集合。利用該JSON文件生成結(jié)構(gòu)化的關(guān)系數(shù)據(jù),存儲于PostgreSQL 數(shù)據(jù)庫中。三個集合(表)的數(shù)據(jù)量分別為20 萬條、150 萬條、600 萬條記錄。為進(jìn)一步測試,根據(jù)原有數(shù)據(jù),為每一個集合(表)又進(jìn)一步生成了兩倍數(shù)據(jù)和四倍數(shù)據(jù)。
本節(jié)介紹優(yōu)化規(guī)則設(shè)定的前期實驗,證明優(yōu)化規(guī)則設(shè)定的合理性。本節(jié)的實驗從單字段查詢、表連接查詢、聚合操作查詢?nèi)矫?,對比關(guān)系數(shù)據(jù)庫PostgreSQL 和文檔數(shù)據(jù)庫MongoDB 在簡單查詢上的查詢性能。
(1)單字段查詢
單字段查詢從整型、字符型、日期型、JSON 字符串類型四種數(shù)據(jù)類型測試。測試所使用的查詢實例如下:
PostgreSQL 與MongoDB 在以上查詢上的時間消耗與對比分別如表2 和圖4 所示。在單字段上的簡單查詢以及聚合操作上,MongoDB 的性能遠(yuǎn)高于PostgreSQL,但是當(dāng)涉及到表連接操作時,哪怕是簡單的兩表連接,PostgreSQL的查詢性能遠(yuǎn)高于Mongo-DB的查詢性能。
Table 2 Simple query time consumption of PostgreSQL and MongoDB表2 PostgreSQL 與MongoDB 簡單查詢時間消耗
Fig.4 Comparison of simple query time between PostgreSQL and MongoDB圖4 PostgreSQL 與MongoDB 簡單查詢時間對比
本實驗的目的是測試執(zhí)行引擎ENTIA對既涉及MongoDB 又涉及PostgreSQL 的混合查詢的查詢處理的正確性,通過與傳統(tǒng)方法的查詢結(jié)果與查詢時間對比,證明ENTIA 對跨引擎查詢處理的可行性。本實驗中采取的查詢實例為查詢Q3.1。針對Q3.1,傳統(tǒng)的解決思路是,程序員手動分別寫出PostgreSQL與MongoDB 兩個查詢,分別向兩個數(shù)據(jù)庫引擎發(fā)送查詢請求,獲取兩部分查詢結(jié)果之后,再手動連接兩部分結(jié)果,得到最終的查詢結(jié)果。
將查詢Q3.1訪問的表business以及集合business的元組(文檔)數(shù)量N分別設(shè)為20萬、40萬、80萬組,對ENTIA 的執(zhí)行情況與傳統(tǒng)思路各測試10 次,記錄時間(單位為ms),并取平均值。ENTIA 與傳統(tǒng)方法分別使用ENTIA-U 與TRAN-U 表示,其查詢時間對比如表3所示。
Table 3 Query time comparison between ENTIA and traditional method表3 ENTIA與傳統(tǒng)方法查詢時間對比
從表3中可以看出,兩種方法的查詢時間幾乎相同。ENTIA由于要將混合查詢進(jìn)行解析、重寫,進(jìn)而再分發(fā)給相應(yīng)的數(shù)據(jù)庫引擎查詢,因此在查詢時間上要略大于傳統(tǒng)思路的查詢時間,兩種方法性能差在0.15%左右,在可接受范圍之內(nèi)。但是ENTIA大大提高了程序開發(fā)效率,降低了程序員對數(shù)據(jù)庫能力的要求,通過訪問ENTIA的接口即可完成跨引擎查詢。
本實驗的目的是測試可優(yōu)化查詢在PostgreSQL、MongoDB以及本文提出的基于啟發(fā)式規(guī)則的優(yōu)化方法的查詢時間,對比三種方法的性能,驗證兩種優(yōu)化方法的正確性和效果。
將上述查詢實例訪問的表(集合)business、user和review 的元組(文檔)數(shù)量N分別設(shè)為(20 萬、150萬、600萬)、(40萬、300萬、1 200萬)、(80萬、600萬、2 400 萬)三組數(shù)據(jù),對PostgreSQL、MongoDB、ENTIA 的執(zhí)行情況各測試十次,記錄時間(單位為ms),并取平均值?;诰酆喜僮鲀?yōu)化規(guī)則的性能對比結(jié)果如表4所示,基于全表掃描優(yōu)化規(guī)則的性能對比結(jié)果如表5所示。
Table 4 Performance comparison based on aggregation operation optimization rules表4 基于聚合操作優(yōu)化規(guī)則的性能對比結(jié)果
Table 5 Performance comparison based on full table scan optimization rules表5 基于全表掃描優(yōu)化規(guī)則的性能對比結(jié)果
圖5為基于聚合操作優(yōu)化規(guī)則下,可優(yōu)化查詢在三種引擎中的查詢性能對比圖。從圖5中可以看出,每個數(shù)量級下ENTIA的執(zhí)行均具有明顯的優(yōu)勢。其次,由于MongoDB 在聚合操作上的查詢性能較高,每個數(shù)量級下MongoDB 的查詢時間均少于Post-greSQL 中的查詢時間。重寫后的查詢,充分利用MongoDB 聚合操作的查詢優(yōu)勢,各引擎并行執(zhí)行查詢?nèi)蝿?wù),大大提高了查詢效率。
Fig.5 Performance comparison graph based on aggregation operation optimization rules圖5 基于聚合操作優(yōu)化規(guī)則的性能對比圖
圖6為基于聚合操作優(yōu)化規(guī)則下,ENTIA相對于PostgreSQL和MongoDB性能提升的趨勢圖。從圖6中可以看出,隨著數(shù)據(jù)量的增大,性能提升的效果越來越明顯。ENTIA使PostgreSQL避免了執(zhí)行聚合操作,使MongoDB避免了執(zhí)行NoSQL數(shù)據(jù)庫所不擅長的連接操作。隨著數(shù)據(jù)量的增大,對于包含聚合操作的不相關(guān)子查詢而言,聚合操作所耗費的時間要遠(yuǎn)遠(yuǎn)大于連接查詢所耗費的時間,也因此,ENTIA相對于兩種數(shù)據(jù)庫引擎而言,性能提升越來越明顯,且相對PostgreSQL的性能提升要高于相對于MongoDB的性能提升。
Fig.6 Performance improvement trend graph based on aggregation operation optimization rules圖6 基于聚合操作優(yōu)化規(guī)則的性能提升趨勢圖
Fig.7 Performance comparison graph based on full table scan optimization rules圖7 基于全表掃描優(yōu)化規(guī)則的性能對比圖
圖7為基于全表掃描優(yōu)化規(guī)則下,可優(yōu)化查詢在三種引擎中的查詢性能對比圖。從圖7中可以看出,每個數(shù)量級下ENTIA的執(zhí)行均具有明顯的優(yōu)勢。分析可優(yōu)化查詢的查詢計劃,時間耗費為子查詢中的全表掃描操作和兩表的Join 操作。當(dāng)執(zhí)行計劃為全表掃描時,其MongoDB 的查詢速度遠(yuǎn)遠(yuǎn)快于在PostgreSQL 中的查詢速度。因此,將子查詢重寫為MongoDB的查詢,大大提高了整個查詢的速度。
圖8為基于全表掃描優(yōu)化規(guī)則下,ENTIA相對于PostgreSQL和MongoDB性能提升的趨勢圖。從圖8中可以看出,隨著數(shù)據(jù)量的增大,性能提升效果越來越明顯。ENTIA 避免了執(zhí)行MongoDB 所不擅長的連接操作與PostgreSQL在大數(shù)據(jù)量下的全表掃描操作。由于表與表之間的連接操作所耗費的時間性能的因素比單字段查詢所耗費的時間性能因素更加明顯,導(dǎo)致ENTIA相對MongoDB的性能提升要高于相對于PostgreSQL的性能提升。
Fig.8 Performance improvement trend graph based on full table scan optimization rules圖8 基于全表掃描優(yōu)化規(guī)則的性能提升趨勢圖
本文基于關(guān)系數(shù)據(jù)庫PostgreSQL和文檔數(shù)據(jù)庫MongoDB 對查詢處理進(jìn)行探索研究,實現(xiàn)執(zhí)行引擎ENTIA,給出了混合查詢的查詢處理,并基于啟發(fā)式規(guī)則對混合引擎進(jìn)行查詢優(yōu)化,提高了查詢效率。在未來的研究工作中,希望進(jìn)行擴展,加入更多NoSQL數(shù)據(jù)庫,使系統(tǒng)支持更加豐富的數(shù)據(jù)類型。
致謝本文工作得到國家電網(wǎng)有限公司科技項目(合同號:SGGSKY00FJJS1900296)的部分支持,也得到了中國人民大學(xué)信息技術(shù)與管理國家級實驗教學(xué)示范中心的部分支持。感謝審稿專家們的寶貴修改意見和建議,同時感謝中國人民大學(xué)數(shù)據(jù)工程與知識工程教育部重點實驗室人大行云云平臺為本論文項目提供的實驗環(huán)境。