張雅文 劉春霞 黨偉超 白尚旺
(太原科技大學計算機科學與技術學院 山西 太原030024)
在SaaS應用中,一個應用實例為多個租戶服務,即雖然多租戶數(shù)據(jù)同屬于一個應用,但是被不同的租戶進行了不同的定制[1-2]。多寬表模式是一種有效存儲多租戶數(shù)據(jù)的解決方法,通過元數(shù)據(jù)驅動實現(xiàn)租戶定制需求[3]。傳統(tǒng)數(shù)據(jù)庫索引是在關系的某個特定屬性列上建立索引,多寬表存儲模式是將所有租戶不同數(shù)據(jù)模式的數(shù)據(jù)共享存儲,所以傳統(tǒng)的數(shù)據(jù)庫索引技術無法適用于多寬表模式[4]。因此本文給出元數(shù)據(jù)驅動下改進的Indexes Pivot Table IIPT(Improved Indexes Pivot Table)索引模型,該模型充當多寬表模式下的租戶邏輯索引,以此提高數(shù)據(jù)訪問速度。
在現(xiàn)階段,面向SaaS應用的多租戶數(shù)據(jù)管理是國內外研究的重要內容,由于多租戶數(shù)據(jù)庫在滿足租戶數(shù)據(jù)隔離和按需定制要求的同時,在性能上也需使用戶有較好的體驗,因此這對數(shù)據(jù)的存儲機制和索引機制提出了挑戰(zhàn)[5]。多租戶數(shù)據(jù)存儲已經(jīng)成為熱點,但是在索引方面的研究還比較少[6]。
SaaS應用采用單個數(shù)據(jù)節(jié)點對多租戶數(shù)據(jù)進行共享存儲,但是由于單個數(shù)據(jù)節(jié)點的能力有限,無法滿足租戶數(shù)量日益增長的要求,因此采用多數(shù)據(jù)節(jié)點進行存儲是必然的[7]。為解決多數(shù)據(jù)節(jié)點大規(guī)模數(shù)據(jù)索引的問題,采用租戶節(jié)點索引、租戶邏輯索引和關系數(shù)據(jù)庫物理索引三級索引相結合的索引模型[8]。租戶節(jié)點索引根據(jù)當前訪問的租戶,定位到存儲該租戶數(shù)據(jù)的數(shù)據(jù)節(jié)點。租戶邏輯索引在單節(jié)點上為租戶數(shù)據(jù)提供支持定制、共享的索引技術,保證租戶快速訪問數(shù)據(jù)。關系數(shù)據(jù)庫索引是一個單獨的、物理的數(shù)據(jù)庫結構,在底層數(shù)據(jù)庫基礎上提供索引技術支持[9]。
本文主要針對單數(shù)據(jù)節(jié)點的索引技術進行研究。單數(shù)據(jù)節(jié)點下的數(shù)據(jù)存儲為共享模式,如果一個租戶在某個屬性上建立索引,其他租戶也會被動地在該屬性建立索引,所以在創(chuàng)建索引時租戶間會相互干擾[10]。為了解決該問題,M-Store提出了單獨建立租戶索引,不僅優(yōu)化了索引結構,而且提高了查詢效率,但是索引數(shù)據(jù)隨著租戶數(shù)量的增加也會越來越多,給數(shù)據(jù)庫造成很大的負擔[11]。Salesforce采用建立Indexes Pivot Table來存儲租戶索引數(shù)據(jù),該方法有效地提高了租戶訪問數(shù)據(jù)的速度,但隨著租戶數(shù)量的增加,Indexes Pivot Table會產(chǎn)生大量的空值,其占用的存儲空間也會暴漲[12-13]。為了解決傳統(tǒng)數(shù)據(jù)庫索引不能適用多寬表共享存儲模式的問題,以及現(xiàn)有的索引模型導致數(shù)據(jù)庫存儲空間增長的問題,給出了一種元數(shù)據(jù)驅動的IIPT索引模型,不僅存儲空間不會隨租戶數(shù)量急速增長,而且有效提高了租戶訪問數(shù)據(jù)的速度。
在SaaS模式下,數(shù)據(jù)庫不但要提供存儲的功能,還要支持租戶按需定制、數(shù)據(jù)隔離以及數(shù)據(jù)擴展。結合國內外研究現(xiàn)狀,同時比較多種存儲模式優(yōu)缺點,本文選擇了多寬表模式來存儲租戶業(yè)務數(shù)據(jù),以及給出一種適合該模式的多租戶索引模型。
在SaaS應用中,多租戶的特性支持單個應用實例被不同租戶進行不同定制。寬表模式作為一種有效解決多租戶數(shù)據(jù)存儲問題的方法,是將所有租戶不同數(shù)據(jù)模式的數(shù)據(jù)存儲到一張寬表中,為了解決寬表存在大量空值的問題,提出了多寬表的存儲模式。
多寬表模式提供較好的可定制性,在該模式下,租戶按需定制數(shù)據(jù)項,將其定制信息保存在元數(shù)據(jù)(MetaDataFields)中,租戶定制的數(shù)據(jù)項經(jīng)過模式映射后,根據(jù)數(shù)據(jù)表的元數(shù)據(jù)信息(MetaTable)存儲在與租戶定制列數(shù)相近的寬表Data x中,多寬表的數(shù)據(jù)定義如圖1所示。
圖1 基于多寬表的多租戶數(shù)據(jù)庫
如表1所示,租戶從視圖層看到的是傳統(tǒng)的關系數(shù)據(jù)模式,但是在實際的多寬表存儲模式中,基于定制的元數(shù)據(jù)信息,該關系通過模式映射機制被透明的轉換到寬表(Data x)中,如表2所示。
表1 租戶1從視圖層看到的關系
表2 租戶1存儲層的關系
多寬表共享存儲多租戶不同業(yè)務下不同的數(shù)據(jù)模式,隨著租戶數(shù)量的不斷增加,數(shù)據(jù)量也會急劇增加,訪問數(shù)據(jù)時通過順序掃描查詢勢必會影響查詢效率,因此建立多寬表數(shù)據(jù)存儲模式下的多租戶索引模型勢在必行。傳統(tǒng)索引是在關系的某個特定屬性列上建立索引,該屬性列下數(shù)據(jù)的數(shù)據(jù)類型、數(shù)據(jù)模式是相同的,但是多寬表存儲著多種不同的數(shù)據(jù)模式,同一屬性列數(shù)據(jù)可能是不同的數(shù)據(jù)類型或代表不同的數(shù)據(jù)含義。因此給出了一種元數(shù)據(jù)驅動改進的Indexes Pivot Table索引模型。
Salesforce建立Indexes Pivot Table存儲索引數(shù)據(jù)。Indexes Pivot Table中包含字段如StringValue、NumValue和DateValue等,Salesforce將索引數(shù)據(jù)按數(shù)據(jù)類型存儲在相應的字段中。例如,Salesforce會將數(shù)據(jù)表中字符串數(shù)據(jù)類型的數(shù)據(jù)復制到索引表中的StringValue字段,日期類型的數(shù)據(jù)復制到DateValue字段等。該Indexes Pivot Table在存儲索引數(shù)據(jù)時,如果其中一個數(shù)據(jù)類型字段存儲了索引數(shù)據(jù),則其他數(shù)據(jù)類型為空值。隨著數(shù)據(jù)量的增大,空值的數(shù)量也會逐漸增大,浪費了存儲空間。針對產(chǎn)生大量空值的情況,對Indexes Pivot Table進行改進,將多種數(shù)據(jù)類型字段合并存儲在一列中,有效解決了空值產(chǎn)生的問題。
本文對多寬表模式的多租戶數(shù)據(jù)庫進行擴展,增加了基于元數(shù)據(jù)驅動改進的Indexes Pivot Table。圖2描述了IIPT多租戶數(shù)據(jù)庫模型,模型中的表分為兩種。一種為元數(shù)據(jù)表,另一種為數(shù)據(jù)表。元數(shù)據(jù)表包括字段元數(shù)據(jù)MetaDataFields、多寬表的元數(shù)據(jù)MetaTable以及索引元數(shù)據(jù)IndexDataTable。數(shù)據(jù)表包括一系列的寬表Data。
圖2 IIPT多租戶數(shù)據(jù)庫模型
下面給出本模型的表結構定義。
定義1MetaDataFields
表示字段元數(shù)據(jù),用于存儲Data寬表的信息以及其中屬性的各種信息。租戶標識TenantId、租戶邏輯私有表標識TableName,以及寬表所屬列名fieldName聯(lián)合作為主鍵,通過RealTableName可以映射出租戶業(yè)務數(shù)據(jù)fieldName實際物理存儲位置,而RealFieldName可以映射Data寬表中fieldName的真正含義。fieldType、fieldLength、isIndexed、DataType分別表示fieldName的屬性:類型、長度、是否為索引、真正的數(shù)據(jù)類型。
定義2MetaTable
表示多寬表的元數(shù)據(jù),用于存儲所有Data寬表的基本信息,包括寬表的表名和列數(shù)等信息,該信息作為租戶選擇寬表進行存儲的依據(jù)。
定義3IndexDataTable
表示索引元數(shù)據(jù),用于共享存儲多寬表的索引。Indexes Pivot Table存儲多種數(shù)據(jù)類型的索引數(shù)據(jù),造成索引表中空值的增多。本文對Indexes Pivot Table進行改進,將多種數(shù)據(jù)類型共同存儲在一列中。通過訪問字段元數(shù)據(jù)表,對于需要建立索引的數(shù)據(jù),將其從寬表復制到索引表中,無需關注數(shù)據(jù)類型。
定義4Data1, Data2, Data x
表示數(shù)據(jù)表,寬表的列數(shù)呈遞增趨勢分布。租戶根據(jù)數(shù)據(jù)模式具有的屬性列數(shù)選擇合適的寬表存儲業(yè)務數(shù)據(jù)。UID是全局唯一標識作為寬表的主鍵,與租戶標識TenantId和租戶邏輯私有表標識TableName一起對租戶的業(yè)務數(shù)據(jù)進行共享存儲,它們的最大列數(shù)分別為valueMax、columnMax、rowMax。
租戶索引具有可定制性,定制過程就是根據(jù)租戶需求及對關系模式中某字段適合作為索引的判斷,將字段元數(shù)據(jù)表(MetaDataFields)中的isIndexed字段設置為yes。在對實時性要求較高的SaaS應用中,如果沒有索引更新策略是不可行的。當業(yè)務數(shù)據(jù)插入、刪除、修改時,索引元數(shù)據(jù)需同時更新;當業(yè)務數(shù)據(jù)查詢時,首先根據(jù)字段元數(shù)據(jù)表判斷是否存在索引,如果存在按照索引查詢,并返回結果,如果不存在,則順序查詢,返回查詢結果。本文給出IIPT索引模型的索引插入算法IIPTIA(Improved Indexes Pivot Table Insert Algorithm),索引刪除算法IIPTDA(Improved Indexes Pivot Table Delete Algorithm),索引更新算法IIPTUA(Improved Indexes Pivot Table Update Algorithm)及查詢算法IIPTQA(Improved Indexes Pivot Table Query Algorithm)。
算法1索引插入算法(IIPTIA)
輸入:insert into R (A,B,…) values(value1,value2,value3,…)
輸出:null
1. 獲取當前租戶標識Tenantid;
2. 根據(jù)輸入語句更新數(shù)據(jù)庫中的業(yè)務數(shù)據(jù)表Data,保存全局唯一標識(UID);
3. 根據(jù)租戶標識Tenantid,for私有表R中的字段A,B,…,在字段元數(shù)據(jù)表MetaDataFields中判斷出R定制的索引列;
4. 取出索引列上更新的值;
5. 根據(jù)索引元數(shù)據(jù)表的結構對索引值進行存儲。
算法2索引刪除算法(IIPTDA)
輸入:delete from R where A=′b′;
輸出:null
1. 獲取當前租戶標識Tenantid;
2. 根據(jù)輸入語句獲得私有表名稱R與列名A,查詢字段元數(shù)據(jù)表MetaDataFields取得實際存儲表名與實際列名;
3. 根據(jù)步驟2得出實際刪除業(yè)務數(shù)據(jù)的SQL語句;
4. 根據(jù)步驟2對實際存儲的表進行查詢,保存要刪除信息的全局唯一標識UID;
5. 根據(jù)步驟4中所得UID對索引表進行刪除操作,由此當對業(yè)務數(shù)據(jù)進行刪除操作時,業(yè)務數(shù)據(jù)所對應的索引數(shù)據(jù)也同步進行刪除。
算法3索引更新算法(IIPTUA)
輸入:update A set B=′b′ where C=′c′;
輸出:null
1. 獲取當前租戶標識Tenantid;
2. 根據(jù)輸入語句獲得私有表名稱R、列名A與列名B,查詢字段元數(shù)據(jù)表MetaDataFields取得實際存儲表名與實際列名,以及set的列是否為索引列;
3. 對sql語句進行解析,獲得索引更新值b與條件值c;
4. 根據(jù)步驟2與步驟3得出實際更新業(yè)務數(shù)據(jù)的SQL語句;
5. 根據(jù)步驟2與步驟3對實際存儲的表進行查詢,保存要更新信息的全局唯一標識UID;
6. if步驟2中結果為yes
根據(jù)步驟5中得到的UID對索引數(shù)據(jù)表進行更新
else步驟2中的結果為no。
無需對索引表進行更新。
算法4數(shù)據(jù)查詢算法(IIPTQA)
輸入:select A,B,… from R where D=value1
輸出:符合條件的目標結果集
1. 獲取當前租戶標識Tenantid;
2. 解析查詢語句中的私有表R和所查字段A,B,…;
3. 查詢字段元數(shù)據(jù)表(MetaDataFields)獲得私有表R實際存儲表名Data,以及所查字段(A,B,…)在Data表中的實際字段名value n(n=1,2,…,n);
4. 查詢字段元數(shù)據(jù)表(MetaDataFields)獲得where條件D是否為索引;
5. If 步驟4中結果為yes
查詢索引元數(shù)據(jù)表(IndexDataTable)獲得數(shù)據(jù)行全局唯一標識UID;
在Data表中,根據(jù)UID字段上的數(shù)據(jù)庫物理索引B-樹,直接查;
返回符合條件的目標數(shù)據(jù)集。
Else 步驟4中的結果為no
依次將A,B,…,D用查詢到的實際字段名value n替換,將R用Data表替換;
替換后拼接成可直接作用于Data表的查詢語句,進行查詢;
返回符合條件的目標數(shù)據(jù)集。
本文實現(xiàn)了基于關系型數(shù)據(jù)庫,在多寬表共享數(shù)據(jù)存儲模式下元數(shù)據(jù)驅動的索引機制。實驗主要針對空值數(shù)量進行分析,并對本文給出的索引策略進行驗證。實驗環(huán)境如下:
數(shù)據(jù)庫版本為MySQL Server 5.5,運行環(huán)境為Eclipse 3.7.2。
在存儲單元的基礎上對空值數(shù)量進行分析,假設存儲N個索引數(shù)據(jù)。若采用Indexes Pivot Table存儲,其中表示數(shù)據(jù)類型的字段有M個,則存在(M-1)×N個空值。
若采用IIPT存儲,所有索引數(shù)據(jù)只存儲在一個字段中,沒有空值產(chǎn)生。
分析可得,采用改進的Indexes Pivot Table,相對于Indexes Pivot Table,解決了空值問題,節(jié)省了存儲空間。
實驗數(shù)據(jù)采用3個關系模式作為實例,分別為:學生(Student)關系模式、課程(Course)關系模式和地址(NativePlace)關系模式。定制關系模式中的一個屬性為索引屬性,分別為CNo、NNo和SOld。3個關系模式的數(shù)據(jù)經(jīng)過模式映射存儲在合適的Data表中,Data表中字段UID上有主碼索引,Data表數(shù)據(jù)量為10 000條。
由租戶發(fā)起insert插入數(shù)據(jù)的更新操作,實驗算法1中的索引插入。例句如下:
insert into Course (CNo,Cname,CGrade) values (8,yuwen,2)
insert into NativePlace(NNo,Nname,NPlace) values (001,wangli,beijing)
insert into Student(SNo,Sname,SSex,SOld,Spart) values (001,wangna,nv,22,jisuanji)
分別更新數(shù)據(jù)到各自的Data表中,如表3和表4所示。
表3 Course和NativePlace所在Data表
表4 Student所在Data表
根據(jù)更新的數(shù)據(jù)對索引表同步更新,如表5所示。
表5 改進的Indexes Pivot Table
以上實驗實現(xiàn)了算法1的索引插入的更新策略。
由租戶發(fā)起delete刪除數(shù)據(jù)的更新操作,實驗算法2中的索引刪除。例句如下:
delete from Student where SNo=′000′
根據(jù)算法2可成功刪除實際存儲表中Student 學號為′000′的數(shù)據(jù),同時也刪除了索引表中該學生的所有索引信息。
由租戶發(fā)起update數(shù)據(jù)的更新操作,實驗算法3中的索引更新。例句如下:
update Student set SOld=′30′ where SNo=′000′
根據(jù)算法3,判斷得出SOld為索引列,因此在更新業(yè)務數(shù)據(jù)的同時對索引表也進行更新。
update Student set SName=′zhangli′ where SNo=′000′
根據(jù)算法3,判斷得出SName不是索引列,因此只需更新業(yè)務數(shù)據(jù),索引表保持不變。
為了模擬多租戶環(huán)境,本實驗開啟40個線程作為40個租戶對數(shù)據(jù)進行操作。記錄有索引機制與沒有索引機制40個租戶分別對數(shù)據(jù)進行查詢的時間,實驗結果如圖3所示。
圖3 查詢時間對比
如圖3所示,圖中上方的曲線是沒有加入索引機制的查詢時間,下方是加入索引機制后的查詢時間。在無索引機制下,40個租戶的平均查詢時間為123.675 ms;在索引機制下,平均查詢時間為30.025 ms,比無索引機制的平均查詢時間低75.72%。通過實驗驗證可得,在兩級索引即租戶邏輯索引和關系數(shù)據(jù)庫物理索引的基礎上,本文給出的算法是可實現(xiàn)的,并且提高了多租戶數(shù)據(jù)查詢效率。
綜上所述,給出的多寬表模式下的索引模型,較好地解決了SaaS應用索引的定制問題,以及在查詢效率上實驗效果也較為理想。
本文基于MySQL關系型數(shù)據(jù)庫,在多寬表數(shù)據(jù)存儲模式下引入改進的Indexes Pivot Table,減少了Indexes Pivot Table作為索引表產(chǎn)生的空值數(shù)量。同時給出了在該模型下的索引維護策略,包含索引更新策略和在索引機制下的查詢策略,通過實驗實現(xiàn)了同步更新索引表以及有效提高數(shù)據(jù)查詢效率。在下一步研究中,如何對索引列更全面地進行設置是需要考慮的問題。