張雅文,劉春霞,白尚旺,黨偉超
(太原科技大學(xué) 計算機科學(xué)與技術(shù)學(xué)院,太原030024)
軟件即服務(wù)(Software as a service, SaaS)是隨著云計算發(fā)展起來的一種新型軟件服務(wù)模式。SaaS環(huán)境下,多租戶數(shù)據(jù)存儲一直是研究領(lǐng)域的熱點。基于寬表的數(shù)據(jù)存儲模式可以有效解決多租戶數(shù)據(jù)存儲問題,表的數(shù)量不會隨著租戶數(shù)量的增加而增加,且由于是整行存儲數(shù)據(jù)也不用進行表的多次連接,但寬表可能會造成大量的空值產(chǎn)生。因此針對SaaS應(yīng)用單實例多租賃的特點,在保證租戶定制需求的基礎(chǔ)上,有必要研究新的數(shù)據(jù)存儲模式,以提高存儲空間利用率和查詢效率。
SaaS模式是通過Internet提供軟件的模式,用戶不需要安裝軟件,只需要連接到網(wǎng)絡(luò)就可以使用SaaS模式提供的軟件[1-2]。用戶可以根據(jù)自身需求以租賃的方式對軟件進行使用,使得成本遠遠要比在本地部署專有軟件的成本低。
數(shù)據(jù)的多租戶化是SaaS應(yīng)用多租戶化的重要組成部分,SaaS應(yīng)用采用一個應(yīng)用實例為多個租戶提供服務(wù)[2-3],各個租戶在視圖層又有不同的數(shù)據(jù)模式,所以需要有一個不同于傳統(tǒng)應(yīng)用的數(shù)據(jù)存儲方案,以實現(xiàn)數(shù)據(jù)的存儲、隔離,及用戶訪問數(shù)據(jù)的便捷性。
目前SaaS多租戶數(shù)據(jù)存儲已有了一些解決方案。例如擴展表方法將租戶共享模式部分公共存儲,租戶單獨模式部分分開存儲,在一定程度上共享了租戶數(shù)據(jù),減少了存儲開銷,但是沒有解決表數(shù)目跟隨租戶數(shù)目的增長而增長;透視表采取垂直存儲的策略,將租戶數(shù)據(jù)拆解成(key,value)的方式進行存儲,這樣減少了空值的數(shù)量,但是元組重組困難,如果想要重組含有n列的某租戶的邏輯表,則需要進行n-1次的連接操作[5]。
Salesforce作為全球最大的SaaS服務(wù)提供商,提出了基于寬表的存儲模式進行數(shù)據(jù)存儲,屬于共享數(shù)據(jù)庫共享模式的數(shù)據(jù)存儲架構(gòu),能夠共用存儲結(jié)構(gòu)和資源,保證資源使用效率[6-7]。寬表存儲數(shù)據(jù)具有很大的稀疏性,可能產(chǎn)生大量的空值,原因有兩種:一是租戶未定制該列,為模式空;二是租戶定制了該列而列值為空,為值空[8]。在寬表的存儲模式下,空值主要為模式空。為減少模式空值的產(chǎn)生,降低空值對數(shù)據(jù)查詢的影響,本文將單寬表的存儲模式擴展為多寬表的存儲模式,并提出將用戶發(fā)起的SQL查詢語句轉(zhuǎn)換為可以直接作用于數(shù)據(jù)庫的SQL查詢語句,以方便租戶查詢數(shù)據(jù)時進行模式映射和查詢重寫。
寬表的存儲模式是一種共享數(shù)據(jù)庫共享模式的數(shù)據(jù)存儲架構(gòu)。由于租戶的數(shù)據(jù)存儲在一張寬表中,所以數(shù)據(jù)表的數(shù)目不會隨租戶數(shù)量的變化而變化,也不會發(fā)生膨脹,節(jié)省了數(shù)據(jù)庫的存儲空間。所以基于寬表的存儲模式是一種有效解決多租戶數(shù)據(jù)存儲問題的模式。
SaaS區(qū)別于傳統(tǒng)軟件的重要差別就是多租戶的模式,多租戶架構(gòu)是SaaS應(yīng)用的基本特性,多個租戶共享一個實例,租戶的數(shù)據(jù)既是隔離的也是共享的[9]。物理層面上,租戶的數(shù)據(jù)共同存儲在同一個數(shù)據(jù)模式下,邏輯層面上,通過租戶特有的標識對其進行區(qū)別,實現(xiàn)數(shù)據(jù)的隔離。
圖 1 多租戶架構(gòu)
Fig.1 Multi-tenancy Infrastructure
圖1描述了寬表模式下的多租戶架構(gòu),包含4個層次。最底層是所有租戶使用的業(yè)務(wù)數(shù)據(jù)以及元數(shù)據(jù),這些數(shù)據(jù)以寬表的方式存儲在數(shù)據(jù)庫中。緊鄰底層的是模式映射和查詢重寫技術(shù)層,相當(dāng)于一個中間件,以實現(xiàn)邏輯視圖與物理存儲結(jié)構(gòu)的透明轉(zhuǎn)換[10]。頂部兩層是SaaS應(yīng)用和租戶應(yīng)用,多個租戶應(yīng)用可以宿主于一個SaaS應(yīng)用。
Salesforce使用的存儲模式是寬表。寬表的主要數(shù)據(jù)結(jié)構(gòu)是由租戶標識Tenantid和屬于租戶的某表的標識TableName,以及N列的數(shù)據(jù)列組成,數(shù)據(jù)列的類型使用可以靈活轉(zhuǎn)換為其他類型的變長字符串類型。
寬表是整行存儲數(shù)據(jù),不需要做大量的連接操作,也符合大部分人的存儲習(xí)慣,這是它最大的優(yōu)勢。但是可能會造成大量的空值,占用存儲空間??梢酝ㄟ^對寬表進行改進,形成多寬表的存儲方式,減少空值的出現(xiàn)。
多寬表的數(shù)據(jù)存儲模式是將單個的寬表用不同列的多表代替來存儲業(yè)務(wù)數(shù)據(jù),通過元數(shù)據(jù)對業(yè)務(wù)數(shù)據(jù)進行描述,元數(shù)據(jù)表保存了租戶數(shù)據(jù)模式與實際物理存儲位置之間的映射關(guān)系。
圖2描述了多寬表存儲模式下的數(shù)據(jù)結(jié)構(gòu)定義。其中包含兩種類型的表:一種為元數(shù)據(jù)表MetaDataFields和MetaTable,另一種為數(shù)據(jù)表DefSQLTable和一系列的寬表DatA.
圖2 多寬表數(shù)據(jù)結(jié)構(gòu)定義
Fig.2 Multiple universal table data structure definition
(1)DefSQLTable表用來存儲租戶邏輯私有表的SQL定義,邏輯私有表也就是租戶視圖層的數(shù)據(jù)模式,該定義中包含了租戶視圖層與數(shù)據(jù)庫層的映射關(guān)系。查詢重寫時根據(jù)租戶查詢請求判斷所請求的SQL定義是否存在,若存在則從該表中獲取對應(yīng)的SQL定義,若不存在則通過訪問元數(shù)據(jù)得到相應(yīng)的SQL定義并存儲在該表中。
(2)MetaTable表用來存儲一系列Data寬表的基本信息,包括寬表的表名和列數(shù)等信息,當(dāng)租戶需要選擇寬表進行存儲時,該信息作為租戶選擇寬表進行存儲的依據(jù)。
(3)MetaDataFields表用來存儲Data寬表的信息以及其中屬性的各種信息。租戶標識TenantId、租戶邏輯私有表標識TableName以及寬表所屬列名fieldName聯(lián)合作為主鍵,通過RealTableName可以映射出租戶業(yè)務(wù)數(shù)據(jù)fieldName實際物理存儲位置,而RealFieldName可以映射Data寬表中fieldName的真正含義。fieldType、fieldLength、NullField分別表示fieldName的屬性:類型、長度、是否為空。
(4)Data1, Data2, Data x表示列數(shù)不同的寬表,寬表的列數(shù)呈遞增趨勢分布。租戶標識TenantId和租戶邏輯私有表標識TableName聯(lián)合作為主鍵,對租戶的業(yè)務(wù)數(shù)據(jù)進行存儲,它們的最大列數(shù)分別為valueMax,columnMax,rowMax.
多寬表的數(shù)據(jù)存儲模式是租戶的業(yè)務(wù)數(shù)據(jù)以多個寬表的形式存儲在數(shù)據(jù)庫中。在該模式下的查詢重寫,是指用戶發(fā)起的邏輯SQL查詢到實際作用于數(shù)據(jù)庫的物理SQL查詢的轉(zhuǎn)換,其中涉及到元數(shù)據(jù)的訪問和SQL重寫。在租戶對數(shù)據(jù)進行查詢時,租戶的數(shù)據(jù)模式與實際存儲模式不同,因此需要轉(zhuǎn)換,對SQL語句重寫,使邏輯SQL語句可以透明轉(zhuǎn)換為物理SQL語句。
在圖2數(shù)據(jù)定義的前提下,對數(shù)據(jù)的SQL查詢進行重寫。方法有兩種,一種是動態(tài)SQL重寫,另一種是視圖定義SQL重寫。
動態(tài)SQL重寫,要先進行復(fù)雜的SQL分析,因為需要對SQL語句的每一項進行解析,重寫過程很復(fù)雜。例如執(zhí)行SQL語句select sold from Student where sno=’1’,首先需要找到Student所在的寬表,其次找到sold對應(yīng)的寬表的列,最后才能根據(jù)sno=’1’進行查詢。如果查詢的列為多項,則在重寫過程中需要動態(tài)地獲得查詢的每一項,并且找到其映射關(guān)系。但是對于簡單的查詢語句,例如select * from Student,只需找到Student所在的寬表,根據(jù)租戶標識以及私有表名Student查詢即可得到結(jié)果。
視圖定義SQL重寫,重寫過程不必對查詢項和涉及的表一一進行解析、映射,簡化了重寫過程。當(dāng)在對租戶信息進行查詢時,先對元數(shù)據(jù)進行訪問,獲得租戶私有表的SQL定義,將其存儲在DefSQLTable中;接著對用戶發(fā)起的SQL查詢語句進行重寫;最后通過物理SQL查詢數(shù)據(jù)進而取得查詢結(jié)果。
私有表SQL定義的生成流程圖如圖3所示。首先輸入要進行SQL定義的租戶標識和租戶私有表名稱;其次從元數(shù)據(jù)表獲得該租戶該私有表的元數(shù)據(jù)映射關(guān)系;然后通過字符串拼接得到SQL定義;最后將其保存在表中。在該存儲模式下,元數(shù)據(jù)只能通過私有表SQL定義過程進行訪問,有效保護了租戶業(yè)務(wù)數(shù)據(jù)的元數(shù)據(jù)。
圖3 私有表SQL定義生成流程圖
Fig.3 Flow chart of private table SQL definition generation
圖4 查詢重寫流程圖
Fig.4 Query rewrite flow chart
查詢重寫的流程圖如圖4所示。首先輸入發(fā)起查詢操作的租戶標識和SQL語句;其次對SQL語句分解、解析,獲得解析所得的表;然后從DefSQLTable表中取出該表的定義,替換SQL語句中涉及的表;最后得到直接作用于數(shù)據(jù)庫的SQL查詢語句。
視圖定義SQL重寫,避免了復(fù)雜的SQL分析,降低了模式映射難度,通過減少SQL重寫時間消耗,整體上提高了查詢效率。
多寬表數(shù)據(jù)存儲模式實驗主要針對存儲空間的利用率進行分析,將其與寬表模式進行比較,并對查詢重寫過程的可行性進行驗證。
模式空是寬表數(shù)據(jù)存儲模式空值大量存在的主要原因,而在多寬表數(shù)據(jù)存儲模式下,不同租戶可以根據(jù)自己數(shù)據(jù)模式的列數(shù),選擇最為接近的寬表進行存儲,可以大大減少模式空值的產(chǎn)生,提高存儲空間的利用率。
假設(shè)要存儲N個租戶數(shù)據(jù)存儲模式,其中模式i具有p行q列。
結(jié)果表明,多寬表的存儲模式有效減少了空值的存在,提高了存儲空間的利用率。
查詢重寫實驗,數(shù)據(jù)庫選擇使用MySQL Server 5.5,運行環(huán)境為Eclipse 3.7.2.
實驗數(shù)據(jù)實例如圖5所示。Coursetenanlid=1表示Course表中租戶1的數(shù)據(jù),表的結(jié)構(gòu)為(CNo,Cname,CGrade),主鍵為CNo;NativePlaceTenantild=2表示NativePlace表中租戶2的數(shù)據(jù),表的結(jié)構(gòu)為(Nno, NName, NPlace),主鍵為Nno.在多寬表的存儲模式中,這兩張表結(jié)構(gòu)是某租戶的數(shù)據(jù)模式,而真正的數(shù)據(jù)是共同存儲在Data表中。
若租戶進行如下SQL查詢:select CGrade from Course where cno='1' .首先對該SQL語句進行分解解析,看是否為簡單SQL語句,判斷為否,得到表Course.然后對SQL定義表進行查詢,看是否存在Course表的SQL定義。如果存在,則進行替換形成作用于數(shù)據(jù)庫的SQL查詢語句;如果不存在,則使用SQL定義的方法對Course表進行定義并存儲后,再取出SQL定義,形成新的SQL查詢語句。通過以上步驟,獲得可以作用于實際數(shù)據(jù)庫的SQL查詢語句:select CGrade from (select value1 as CNo,value2 as CName,value3 as CGrade from data1 where TenantId=‘1’ and TableName=‘Course’) as a where cno=‘1’.通過程序訪問數(shù)據(jù)庫可得到結(jié)果為2.
圖5 實驗數(shù)據(jù)實例
Fig.5 Experimental data example
若租戶進行如下SQL查詢:select * from CoursE.首先對該SQL語句進行分解解析,看是否為簡單SQL語句,判斷為是。通過查詢元數(shù)據(jù)表得到Course所在寬表,然后重寫SQL語句為select * from data1 where TenantId=‘1’ and TableName=‘Course’,最后執(zhí)行該語句所得結(jié)果為:1 yuwen 2. 對于這樣的簡單SQL語句,使用動態(tài)SQL重寫方法要更為簡單,不必再訪問SQL定義表,簡化了重寫過程,節(jié)約了查詢時間。
討論了基于寬表的多租戶數(shù)據(jù)存儲模式,及該模式下的數(shù)據(jù)查詢重寫過程。在分析多租戶寬表存儲模式的特點和存在的缺陷后,將其改進為基于多寬表的數(shù)據(jù)存儲模式,通過實驗驗證減少了數(shù)據(jù)模式空值,提高了存儲空間利用率。并提出在多寬表的數(shù)據(jù)存儲模式下,采用動態(tài)SQL重寫和視圖定義SQL重寫兩種方法對租戶發(fā)起的SQL查詢進行重寫,使之成為可以直接作用于實際數(shù)據(jù)庫的SQL語句。但對數(shù)據(jù)的增加,刪除,修改等其他操作,還需要進一步研究多寬表數(shù)據(jù)存儲模式,提出新的SQL重寫過程。