本發(fā)明涉及數(shù)據(jù)處理
技術(shù)領(lǐng)域:
:,特別涉及一種利用簡(jiǎn)單路徑特征優(yōu)化樹(shù)狀結(jié)構(gòu)數(shù)據(jù)的方法及系統(tǒng)。
背景技術(shù):
::隨著計(jì)算機(jī)網(wǎng)絡(luò)和大數(shù)據(jù)處理技術(shù)的發(fā)展,傳統(tǒng)關(guān)系型數(shù)據(jù)已經(jīng)越來(lái)越不能滿足網(wǎng)絡(luò)和大數(shù)據(jù)環(huán)境下對(duì)數(shù)據(jù)定義和使用的要求,而以json和protocolbuffers為代表的半結(jié)構(gòu)化數(shù)據(jù)因?yàn)榧饶軌虺浞值谋磉_(dá)編程語(yǔ)言中對(duì)象(object)的數(shù)據(jù),同時(shí)還能夠根據(jù)數(shù)據(jù)的格式變化對(duì)原有的數(shù)據(jù)格式進(jìn)行修改和擴(kuò)充,故而其在實(shí)際環(huán)境中被廣泛的使用。樹(shù)狀結(jié)構(gòu)數(shù)據(jù)的定義:tvalue=tprimitive|tobject|tarraytprimitive=string|number|boolean|nullrecord=tobject如上所示,樹(shù)狀結(jié)構(gòu)數(shù)據(jù)定義如下:1.樹(shù)狀結(jié)構(gòu)數(shù)據(jù)中的值可以是以下的3種:object結(jié)構(gòu)的數(shù)值;array結(jié)構(gòu)的數(shù)值;原子類型的數(shù)值;2.object結(jié)構(gòu)的數(shù)值由花括號(hào)包括,內(nèi)部由多個(gè)鍵值對(duì)(keyvaluepair)對(duì)構(gòu)成,鍵值對(duì)的個(gè)數(shù)可以是任意多個(gè),但是要求不能有重復(fù)的key存在在object結(jié)構(gòu)的對(duì)象中;3.array結(jié)構(gòu)的數(shù)據(jù)由方括號(hào)包括,內(nèi)部由多個(gè)值(value)構(gòu)成,值的個(gè)數(shù)可是任意多個(gè),且可能會(huì)有重復(fù)的值出現(xiàn);4.原子類型的數(shù)據(jù)可以是字符串(string),數(shù)值(number),布爾值(boolean)和空(null)等;5.如上2中所述的鍵值對(duì)中,鍵的取值只能是(string)類型的。6.每一個(gè)樹(shù)狀結(jié)構(gòu)的數(shù)據(jù)都是object結(jié)構(gòu)的。常見(jiàn)的數(shù)據(jù)的來(lái)源由以下幾個(gè)方面:1)數(shù)據(jù)資料(datafeeds)以twitter為代表的在網(wǎng)絡(luò)中使用json格式對(duì)數(shù)據(jù)進(jìn)行傳輸。用戶及相關(guān)api程序可以通過(guò)監(jiān)聽(tīng)相應(yīng)的端口獲得相應(yīng)的數(shù)據(jù)更新。由于其數(shù)據(jù)內(nèi)容豐富、結(jié)構(gòu)相對(duì)復(fù)雜、數(shù)據(jù)來(lái)源比較穩(wěn)定并且提供的數(shù)據(jù)量足夠大,故本發(fā)明的實(shí)驗(yàn)和數(shù)據(jù)分析的過(guò)程中主要基于twitter數(shù)據(jù)集。如下,本發(fā)明分析了對(duì)twitter數(shù)據(jù)中的嵌套層次和重復(fù)域的個(gè)數(shù)進(jìn)行了相應(yīng)的分析。2)在線數(shù)據(jù)服務(wù)(onlinedataservice)使用json格式的數(shù)據(jù)進(jìn)行在線的數(shù)據(jù)服務(wù)。常見(jiàn)的類型為傳輸客戶端的相應(yīng)操作內(nèi)容和返回對(duì)應(yīng)的操作結(jié)果等。本發(fā)明研究了不同來(lái)源的在線數(shù)據(jù)服務(wù)的半結(jié)構(gòu)化數(shù)據(jù),例如雅虎(yahoo),新浪微博和imdb等。通常用戶可以使葉子節(jié)點(diǎn)層次沒(méi)有重復(fù)域1個(gè)重復(fù)域多余2個(gè)重復(fù)域總計(jì)1160016261203335121476411942450120126012012總計(jì)129668203用json根據(jù)一定api接口格式編輯數(shù)據(jù)服務(wù)的需求,發(fā)送給相應(yīng)的數(shù)據(jù)服務(wù)器之后,解析json格式的返回?cái)?shù)據(jù)從而完成一次數(shù)據(jù)服務(wù)。本發(fā)明中對(duì)微博api的在線數(shù)據(jù)服務(wù)進(jìn)行了相關(guān)的分析如圖1所示。本發(fā)明重點(diǎn)分析了其路徑中包含的重復(fù)的域的個(gè)數(shù):圖中黑色部分為從根到葉子節(jié)點(diǎn)沒(méi)有重復(fù)域的路徑,淺色部分為僅有1個(gè)重復(fù)域的路徑,白色部分為有2個(gè)以上重復(fù)域的路徑。本發(fā)明中使用統(tǒng)計(jì)直方圖的方式顯示其構(gòu)成的比例:大部分語(yǔ)法樹(shù)中從根到葉子節(jié)點(diǎn)的路徑最多只有1個(gè)重復(fù)的域。3)通信協(xié)議本發(fā)明分析了apachehadoop和hadoophbase中通信相關(guān)的協(xié)議格式,其使用的是protocolbuffers定義的半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行通信相關(guān)的數(shù)據(jù)傳輸。在以上的系統(tǒng)中,定義了多種不同類型的半結(jié)構(gòu)化通信格式,用于不同機(jī)器間的相互通信和控制。大部分用于通信的半結(jié)構(gòu)化數(shù)據(jù)的格式十分簡(jiǎn)單。本發(fā)明中對(duì)apachehadoop的通信協(xié)議進(jìn)行了相關(guān)的分析如圖2所示。本發(fā)明重點(diǎn)分析了其路徑中包含的重復(fù)的域的個(gè)數(shù):圖2中黑色部分為從根到葉子節(jié)點(diǎn)沒(méi)有重復(fù)域的路徑,淺色部分為僅有1個(gè)重復(fù)域的路徑,白色部分為有2個(gè)以上重復(fù)域的路徑。本發(fā)明中使用統(tǒng)計(jì)直方圖的方式顯示其構(gòu)成的比例:大部分語(yǔ)法樹(shù)中從根到葉子節(jié)點(diǎn)的路徑最多只有1個(gè)重復(fù)的域。4)公用數(shù)據(jù)集通過(guò)分析dbpedia和data.gov中的數(shù)據(jù),其使用json格式的數(shù)據(jù)進(jìn)行公用數(shù)據(jù)集的存儲(chǔ)。但是區(qū)別于傳統(tǒng)意義上的半結(jié)構(gòu)化數(shù)據(jù)文件,這些數(shù)據(jù)集中的數(shù)據(jù)僅由一條json數(shù)據(jù)組成。這條記錄主要分為兩部分:第一部分由一個(gè)嵌套子結(jié)構(gòu)(json中的object)構(gòu)成,存儲(chǔ)了之后數(shù)據(jù)集合中數(shù)據(jù)的格式;第二部分則由一個(gè)數(shù)組存儲(chǔ)每條記錄的內(nèi)容,且每條記錄均為沒(méi)有嵌套的結(jié)構(gòu)。本發(fā)明可以很輕松的將這條記錄拆分成數(shù)據(jù)定義和數(shù)據(jù)內(nèi)容兩部分,進(jìn)而使用傳統(tǒng)的半結(jié)構(gòu)化數(shù)據(jù)處理的方法進(jìn)行處理。5)傳感器數(shù)據(jù)最新的傳感器平臺(tái),例如arduino,dragonboard,beaglebone等,均能夠產(chǎn)生和處理json類型的數(shù)據(jù)。本發(fā)明分析了以上來(lái)源的數(shù)據(jù),發(fā)現(xiàn)其數(shù)據(jù)內(nèi)部的格式更加的簡(jiǎn)單:數(shù)據(jù)中所有域的嵌套深度最多為2且最多只會(huì)有一個(gè)多值域出現(xiàn)在從根到葉子節(jié)點(diǎn)的路徑上。但是現(xiàn)階段已有的數(shù)據(jù)處理系統(tǒng)不能對(duì)以上來(lái)源的json格式的半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行很好的處理:既能夠提供完整功能的前提下,同時(shí)各項(xiàng)操作有較好的性能。本發(fā)明分析了大量支持半結(jié)構(gòu)化數(shù)據(jù)管理系統(tǒng),其對(duì)半結(jié)構(gòu)化數(shù)據(jù)的處理思路主要有以下三點(diǎn):1)擴(kuò)展傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)的功能例如postgresql和oracle等,將json等半結(jié)構(gòu)化數(shù)據(jù)以文本或者內(nèi)部編碼的二進(jìn)制格式的以一個(gè)連續(xù)的數(shù)據(jù)塊的形式存儲(chǔ)關(guān)系型數(shù)據(jù)庫(kù)的表中。在進(jìn)行相應(yīng)的查詢操作時(shí),調(diào)用內(nèi)部的解析函數(shù)對(duì)數(shù)據(jù)塊中的內(nèi)容進(jìn)行解析,讀取需要的域中的數(shù)據(jù)值。接下來(lái)調(diào)用關(guān)系型數(shù)據(jù)庫(kù)中的運(yùn)算函數(shù)對(duì)其進(jìn)行相應(yīng)的查詢操作。2)nosql數(shù)據(jù)處理系統(tǒng)內(nèi)部使用更加靈活的方式對(duì)半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行二進(jìn)制的編碼,例如mongodb等。其優(yōu)勢(shì)在于能夠?qū)崿F(xiàn)對(duì)原生的半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行解析、存儲(chǔ)和查詢操作,具有較強(qiáng)的數(shù)據(jù)存儲(chǔ)和查詢優(yōu)勢(shì)。其在實(shí)現(xiàn)的過(guò)程中,根據(jù)半結(jié)構(gòu)化數(shù)據(jù)的結(jié)構(gòu)特點(diǎn),新定義了或者擴(kuò)展了一些查詢相關(guān)的操作。3)列式數(shù)據(jù)格式對(duì)數(shù)據(jù)進(jìn)行處理googleprotocolbuffers和apachehive+parquet支持對(duì)半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行數(shù)據(jù)的處理和查詢等操作。相較于以上兩類基于行式數(shù)據(jù)的數(shù)據(jù)處理系統(tǒng),列式數(shù)據(jù)處理系統(tǒng)能夠在大部分情況下能夠提供更好的查詢分析性能,但是其內(nèi)部實(shí)現(xiàn)更加的復(fù)雜:內(nèi)部通常使用列簇的形式對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ)。對(duì)于半結(jié)構(gòu)化數(shù)據(jù)解析和查詢操作的實(shí)現(xiàn)有較高的難度?,F(xiàn)階段以上3種實(shí)現(xiàn)半結(jié)構(gòu)化數(shù)據(jù)處理系統(tǒng)的方法均存在不同程度的問(wèn)題。1)擴(kuò)展已有的關(guān)系型數(shù)據(jù)庫(kù)支持半結(jié)構(gòu)化數(shù)據(jù)的處理相當(dāng)?shù)托ㄟ^(guò)分析現(xiàn)階段可支持半結(jié)構(gòu)化數(shù)據(jù)處理的關(guān)系型數(shù)據(jù)庫(kù),發(fā)現(xiàn)大部分的數(shù)據(jù)庫(kù)都沒(méi)有針對(duì)半結(jié)構(gòu)化數(shù)據(jù)的結(jié)構(gòu)和數(shù)據(jù)特點(diǎn)進(jìn)行對(duì)應(yīng)的數(shù)據(jù)編碼和優(yōu)化。其主要是將半結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)為文本數(shù)據(jù)塊的形式,通過(guò)其內(nèi)部實(shí)現(xiàn)的一些數(shù)據(jù)解析函數(shù)對(duì)文本類型的數(shù)據(jù)塊進(jìn)行解析,從而得到每條記錄中需要的信息。這樣在數(shù)據(jù)庫(kù)中直接存儲(chǔ)文本類型的json格式數(shù)據(jù)浪費(fèi)了大量的空間。同時(shí)在數(shù)據(jù)查詢的過(guò)程中,需要大量的字符串比較和查詢操作,從而極大的限制了數(shù)據(jù)處理的效率。根據(jù)本發(fā)明已有的研究,雖然很多系統(tǒng)支持半結(jié)構(gòu)化數(shù)據(jù)的運(yùn)算,但是當(dāng)數(shù)據(jù)量增加時(shí),其查詢的運(yùn)行時(shí)間往往太長(zhǎng)而導(dǎo)致其難以滿足實(shí)時(shí)性的要求。關(guān)系型數(shù)據(jù)庫(kù)同時(shí)還不能很好的支持半結(jié)構(gòu)化數(shù)據(jù)中一些新的結(jié)構(gòu)特點(diǎn)。例如直接支持對(duì)嵌套和重復(fù)域的語(yǔ)法定義、擴(kuò)展sql查詢語(yǔ)法支持半結(jié)構(gòu)化數(shù)據(jù)結(jié)構(gòu)特點(diǎn)。2)nosql數(shù)據(jù)處理系統(tǒng)對(duì)數(shù)據(jù)的編碼和查詢效率不夠好本發(fā)明分析并研究了被廣泛使用的nosql數(shù)據(jù)處理系統(tǒng)mongodb。由于json數(shù)據(jù)語(yǔ)義的靈活性,mongodb內(nèi)部定義了冗余且繁瑣的數(shù)據(jù)編碼格式。研究中發(fā)現(xiàn),其編碼的效率十分低下,在大部分情況下,其編碼后的數(shù)據(jù)文件會(huì)大于原有的文本格式的數(shù)據(jù)。數(shù)據(jù)內(nèi)部的編碼并沒(méi)有有效的減少json文本數(shù)據(jù)中的冗余信息,相反在查詢過(guò)程中還會(huì)帶來(lái)額外的性能消耗。這就使得其數(shù)據(jù)處理的性能相對(duì)有限,尤其是對(duì)于海量數(shù)據(jù)的處理。同時(shí),這些nosql數(shù)據(jù)處理系統(tǒng)由于其內(nèi)部設(shè)計(jì)的局限性導(dǎo)致其有些操作無(wú)法執(zhí)行。例如,mongodb中無(wú)法高效的完整實(shí)現(xiàn)sql中的join連接運(yùn)算(雖然在最新版本中加入了相關(guān)的類似的運(yùn)算符,但是依然沒(méi)有完全滿足sql中定義的join連接運(yùn)算且執(zhí)行的效率太低)。3)列式數(shù)據(jù)格式處理數(shù)據(jù)在關(guān)系型數(shù)據(jù)庫(kù)中,列式數(shù)據(jù)庫(kù)的存儲(chǔ)和查詢性能一般都會(huì)優(yōu)于行式數(shù)據(jù)庫(kù)。這是因?yàn)槠湓诓樵冞^(guò)程中不需要讀取并處理記錄中和當(dāng)前查詢無(wú)關(guān)的域的數(shù)據(jù)。但是其內(nèi)部原理復(fù)雜、功能實(shí)現(xiàn)相對(duì)困難。類似的,在支持對(duì)半結(jié)構(gòu)化數(shù)據(jù)處理的系統(tǒng)中,使用列式數(shù)據(jù)進(jìn)行存儲(chǔ)和查詢的系統(tǒng)內(nèi)部也更加復(fù)雜。大部分使用行式數(shù)據(jù)的管理系統(tǒng)中對(duì)json內(nèi)部格式?jīng)]有語(yǔ)法的限制,既其數(shù)據(jù)的內(nèi)容不需要預(yù)先的定義、在使用過(guò)程中數(shù)據(jù)的結(jié)構(gòu)可以不斷的衍變。但是對(duì)于列式的數(shù)據(jù)管理系統(tǒng)而言,需要預(yù)先給出列式數(shù)據(jù)的定義(schema)且在使用過(guò)程中無(wú)法動(dòng)態(tài)變化數(shù)據(jù)的結(jié)構(gòu)。這就極大的限制了半結(jié)構(gòu)化數(shù)據(jù)的靈活性。此外,現(xiàn)階段也沒(méi)有很多的基于列式數(shù)據(jù)的半結(jié)構(gòu)化數(shù)據(jù)處理系統(tǒng)可供用戶選擇??晒┯脩羰褂玫牧惺较到y(tǒng)現(xiàn)階段只有基于java實(shí)現(xiàn)的apachehive+parquet。由于java編程語(yǔ)言的限制,其查詢的效率還有進(jìn)一步優(yōu)化的空間。而其運(yùn)行的平臺(tái)需要apachehadoop和hdfs的支持,所以系統(tǒng)初始化和運(yùn)行的代價(jià)都很高。本發(fā)明在進(jìn)行對(duì)半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行處理等相關(guān)研究時(shí),發(fā)現(xiàn)現(xiàn)有的三種可行性方案均因?qū)Π虢Y(jié)構(gòu)化數(shù)據(jù)處理時(shí)對(duì)數(shù)據(jù)結(jié)構(gòu)和實(shí)現(xiàn)的局限性導(dǎo)致的。首先,半結(jié)構(gòu)化數(shù)據(jù)中內(nèi)部的結(jié)構(gòu)特點(diǎn)導(dǎo)致對(duì)其的數(shù)據(jù)處理不能通過(guò)擴(kuò)展關(guān)系型數(shù)據(jù)庫(kù)得到。兩者對(duì)于數(shù)據(jù)格式有不同的假設(shè),所以在使用關(guān)系型數(shù)據(jù)庫(kù)處理半結(jié)構(gòu)化數(shù)據(jù)時(shí)會(huì)產(chǎn)生更高的代價(jià)以至于難以承受。所以本發(fā)明重新設(shè)計(jì)并實(shí)現(xiàn)了面向于半結(jié)構(gòu)化數(shù)據(jù)數(shù)據(jù)處理系統(tǒng),使得其能滿足對(duì)復(fù)雜結(jié)構(gòu)的半結(jié)構(gòu)化數(shù)據(jù)的處理。其次,考慮到半結(jié)構(gòu)化數(shù)據(jù)定義的靈活及使用過(guò)程中可能會(huì)出現(xiàn)結(jié)構(gòu)變化等特點(diǎn),現(xiàn)階段大部分nosql數(shù)據(jù)管理系統(tǒng)直接使用類本文結(jié)構(gòu)的數(shù)據(jù)對(duì)其進(jìn)行存儲(chǔ)。這就導(dǎo)致了其存儲(chǔ)效率太低且查詢時(shí)的取值過(guò)程代價(jià)很高。在本發(fā)明的設(shè)計(jì)中,從數(shù)據(jù)中提取的結(jié)構(gòu)存儲(chǔ)在schema語(yǔ)法定義中,在數(shù)據(jù)中僅保留最少的結(jié)構(gòu)信息。這樣就簡(jiǎn)化了數(shù)據(jù)中重復(fù)的結(jié)構(gòu)信息,同時(shí)也使得針對(duì)數(shù)據(jù)內(nèi)容的一些查詢優(yōu)化成為可能。最后,現(xiàn)階段基于java實(shí)現(xiàn)的列式半結(jié)構(gòu)化存儲(chǔ)需要很多基礎(chǔ)模塊的支持,例如文件存儲(chǔ)系統(tǒng)、調(diào)度系統(tǒng)等。這些都會(huì)導(dǎo)致其對(duì)系統(tǒng)的功能和使用有一些額外的限制且會(huì)導(dǎo)致其執(zhí)行的效率不高。本發(fā)明基于c/c++實(shí)現(xiàn)的本數(shù)據(jù)處理系統(tǒng)(steed)完全獨(dú)立開(kāi)發(fā),這就使得系統(tǒng)從成整體進(jìn)行優(yōu)化成為可能;也不會(huì)有諸如需要預(yù)先對(duì)數(shù)據(jù)的格式進(jìn)行定義且無(wú)法改變等由于平臺(tái)而產(chǎn)生的限制。技術(shù)實(shí)現(xiàn)要素:針對(duì)現(xiàn)有技術(shù)的不足,本發(fā)明提出一種利用簡(jiǎn)單路徑特征優(yōu)化樹(shù)狀結(jié)構(gòu)數(shù)據(jù)的方法及系統(tǒng)。本發(fā)明提供一種利用簡(jiǎn)單路徑特征優(yōu)化的樹(shù)狀結(jié)構(gòu)數(shù)據(jù)處理方法,包括:步驟1,設(shè)置簡(jiǎn)單路徑,其中所述簡(jiǎn)單路徑為在樹(shù)狀結(jié)構(gòu)數(shù)據(jù)定義的語(yǔ)法樹(shù)中,從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)最多只存在一個(gè)多值的域的路徑;步驟2,通過(guò)存儲(chǔ)所述簡(jiǎn)單路徑中葉子節(jié)點(diǎn)的相關(guān)結(jié)構(gòu)信息,從樹(shù)狀結(jié)構(gòu)數(shù)據(jù)定義的語(yǔ)法樹(shù)中獲取完整的路徑結(jié)構(gòu)信息;步驟3,在使用列式結(jié)構(gòu)數(shù)據(jù)進(jìn)行查詢的過(guò)程中,使用簡(jiǎn)單路徑對(duì)列式結(jié)構(gòu)數(shù)據(jù)到行式結(jié)構(gòu)數(shù)據(jù)的組裝過(guò)程進(jìn)行優(yōu)化:簡(jiǎn)化行式結(jié)構(gòu)數(shù)據(jù)中的嵌套關(guān)系,僅通過(guò)葉子節(jié)點(diǎn)表示從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑而忽略路徑中所有的非葉子節(jié)點(diǎn)。利用半結(jié)構(gòu)化數(shù)據(jù)定義中葉子節(jié)點(diǎn)的相關(guān)信息從語(yǔ)法樹(shù)中獲得整個(gè)路徑的結(jié)構(gòu)信息。對(duì)列式結(jié)構(gòu)樹(shù)狀數(shù)據(jù)組裝為行式結(jié)構(gòu)數(shù)據(jù)之前,對(duì)待組裝的每一條列式結(jié)構(gòu)的路徑按照葉子節(jié)點(diǎn)的id進(jìn)行相應(yīng)的排序,之后,依次按照順序從每個(gè)列式數(shù)據(jù)讀取器中讀取中每條記錄所有的列數(shù)據(jù)項(xiàng),依次將讀出的數(shù)值與相關(guān)的結(jié)構(gòu)信息寫入到組裝的結(jié)果中。對(duì)于語(yǔ)法樹(shù)中的非簡(jiǎn)單路徑,依然按照樹(shù)狀結(jié)構(gòu)數(shù)據(jù)典型的使用多層嵌套結(jié)構(gòu)表示其結(jié)構(gòu)和數(shù)據(jù)的方法進(jìn)行存儲(chǔ)。還包括:1)當(dāng)語(yǔ)法樹(shù)中從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上沒(méi)有重復(fù)節(jié)點(diǎn)的域:僅需要存儲(chǔ)葉子節(jié)點(diǎn)的id與相應(yīng)域的數(shù)值;2)當(dāng)語(yǔ)法樹(shù)中從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上只有一個(gè)重復(fù)節(jié)點(diǎn)的域:按照以下兩種結(jié)構(gòu)進(jìn)行存儲(chǔ):a)將每個(gè)重復(fù)域的數(shù)值都作為一個(gè)獨(dú)立的值存儲(chǔ)在扁平的行式結(jié)構(gòu)數(shù)據(jù)中,所以,數(shù)據(jù)中會(huì)有多項(xiàng)有相同id的值,其個(gè)數(shù)決定于重復(fù)域中其值的個(gè)數(shù);b)將重復(fù)的域作為一個(gè)整體存儲(chǔ)在扁平的行式結(jié)構(gòu)數(shù)據(jù)中,其中數(shù)據(jù)中僅有一個(gè)重復(fù)域的id表示其在數(shù)據(jù)中多次出現(xiàn)的值,且所述重復(fù)域是由一個(gè)數(shù)組形式的結(jié)構(gòu)表示多個(gè)數(shù)值;3)語(yǔ)法樹(shù)從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上有多個(gè)重復(fù)的節(jié)點(diǎn):使用默認(rèn)的樹(shù)狀數(shù)據(jù)存儲(chǔ)結(jié)構(gòu),其中在扁平結(jié)構(gòu)的數(shù)據(jù)中存儲(chǔ)的id為路徑上嵌套層次為1的id,其對(duì)應(yīng)的偏移量指向存儲(chǔ)完整嵌套結(jié)構(gòu)的位置。本發(fā)明還提出一種利用簡(jiǎn)單路徑特征優(yōu)化的樹(shù)狀結(jié)構(gòu)數(shù)據(jù)處理系統(tǒng),包括:簡(jiǎn)單路徑模塊,用于設(shè)置簡(jiǎn)單路徑,其中所述簡(jiǎn)單路徑為在樹(shù)狀結(jié)構(gòu)數(shù)據(jù)定義的語(yǔ)法樹(shù)中,從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)最多只存在一個(gè)多值的域的路徑;獲取數(shù)據(jù)模塊,用于通過(guò)存儲(chǔ)所述簡(jiǎn)單路徑中葉子節(jié)點(diǎn)的相關(guān)結(jié)構(gòu)信息,從樹(shù)狀結(jié)構(gòu)數(shù)據(jù)定義的語(yǔ)法樹(shù)中獲取完整的路徑結(jié)構(gòu)信息;組裝模塊,用于在使用列式結(jié)構(gòu)數(shù)據(jù)進(jìn)行查詢的過(guò)程中,使用簡(jiǎn)單路徑對(duì)列式結(jié)構(gòu)數(shù)據(jù)到行式結(jié)構(gòu)數(shù)據(jù)的組裝過(guò)程進(jìn)行優(yōu)化:簡(jiǎn)化行式結(jié)構(gòu)數(shù)據(jù)中的嵌套關(guān)系,僅通過(guò)葉子節(jié)點(diǎn)表示從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑而忽略路徑中所有的非葉子節(jié)點(diǎn)。利用半結(jié)構(gòu)化數(shù)據(jù)定義中葉子節(jié)點(diǎn)的相關(guān)信息從語(yǔ)法樹(shù)中獲得整個(gè)路徑的結(jié)構(gòu)信息。對(duì)列式結(jié)構(gòu)樹(shù)狀數(shù)據(jù)組裝為行式結(jié)構(gòu)數(shù)據(jù)之前,對(duì)待組裝的每一條列式結(jié)構(gòu)的路徑按照葉子節(jié)點(diǎn)的id進(jìn)行相應(yīng)的排序,之后,依次按照順序從每個(gè)列式數(shù)據(jù)讀取器中讀取中每條記錄所有的列數(shù)據(jù)項(xiàng),依次將讀出的數(shù)值與相關(guān)的結(jié)構(gòu)信息寫入到組裝的結(jié)果中。對(duì)于語(yǔ)法樹(shù)中的非簡(jiǎn)單路徑,依然按照樹(shù)狀結(jié)構(gòu)數(shù)據(jù)典型的使用多層嵌套結(jié)構(gòu)表示其結(jié)構(gòu)和數(shù)據(jù)的方法進(jìn)行存儲(chǔ)。還包括:1)當(dāng)語(yǔ)法樹(shù)中從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上沒(méi)有重復(fù)節(jié)點(diǎn)的域:僅需要存儲(chǔ)葉子節(jié)點(diǎn)的id與相應(yīng)域的數(shù)值;2)當(dāng)語(yǔ)法樹(shù)中從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上只有一個(gè)重復(fù)節(jié)點(diǎn)的域:按照以下兩種結(jié)構(gòu)進(jìn)行存儲(chǔ):a)將每個(gè)重復(fù)域的數(shù)值都作為一個(gè)獨(dú)立的值存儲(chǔ)在扁平的行式結(jié)構(gòu)數(shù)據(jù)中,所以,數(shù)據(jù)中會(huì)有多項(xiàng)有相同id的值,其個(gè)數(shù)決定于重復(fù)域中其值的個(gè)數(shù);b)將重復(fù)的域作為一個(gè)整體存儲(chǔ)在扁平的行式結(jié)構(gòu)數(shù)據(jù)中,其中數(shù)據(jù)中僅有一個(gè)重復(fù)域的id表示其在數(shù)據(jù)中多次出現(xiàn)的值,且所述重復(fù)域是由一個(gè)數(shù)組形式的結(jié)構(gòu)表示多個(gè)數(shù)值;3)語(yǔ)法樹(shù)從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上有多個(gè)重復(fù)的節(jié)點(diǎn):使用默認(rèn)的樹(shù)狀數(shù)據(jù)存儲(chǔ)結(jié)構(gòu),其中在扁平結(jié)構(gòu)的數(shù)據(jù)中存儲(chǔ)的id為路徑上嵌套層次為1的id,其對(duì)應(yīng)的偏移量指向存儲(chǔ)完整嵌套結(jié)構(gòu)的位置。由以上方案可知,本發(fā)明的優(yōu)點(diǎn)在于:1,半結(jié)構(gòu)化數(shù)據(jù)的行式存儲(chǔ)結(jié)構(gòu);實(shí)現(xiàn)對(duì)半結(jié)構(gòu)化數(shù)據(jù)的行式二進(jìn)制存儲(chǔ),使其能夠完整的表達(dá)半結(jié)構(gòu)化數(shù)據(jù)的語(yǔ)義并適應(yīng)其數(shù)據(jù)定義變化的特點(diǎn)。此外,要求其結(jié)構(gòu)簡(jiǎn)單、易于表達(dá),具有較高的存儲(chǔ)效率;2,半結(jié)構(gòu)化數(shù)據(jù)的列式存儲(chǔ)結(jié)構(gòu);實(shí)現(xiàn)對(duì)半結(jié)構(gòu)化數(shù)據(jù)的列式二進(jìn)制存儲(chǔ),使其能夠使用列式存儲(chǔ)完整表達(dá)半結(jié)構(gòu)化數(shù)據(jù)的結(jié)構(gòu)。要求其能夠表達(dá)半結(jié)構(gòu)化數(shù)據(jù)復(fù)雜的結(jié)構(gòu)特點(diǎn)并高效的存儲(chǔ)數(shù)據(jù)的內(nèi)容;3,半結(jié)構(gòu)化數(shù)據(jù)行式和列式兩種格式的相互轉(zhuǎn)化實(shí)現(xiàn);使用解析和組裝算法實(shí)現(xiàn)二進(jìn)制行式和列式數(shù)據(jù)相互轉(zhuǎn)化;4,半結(jié)構(gòu)化數(shù)據(jù)定義的語(yǔ)法樹(shù)實(shí)現(xiàn);使用樹(shù)形結(jié)構(gòu)存儲(chǔ)數(shù)據(jù)中結(jié)構(gòu)的定義信息;5,對(duì)半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行查詢操作;使用行式及列式數(shù)據(jù)對(duì)其進(jìn)行類sql的查詢操作;6,基于半結(jié)構(gòu)化數(shù)據(jù)的特點(diǎn),擴(kuò)展sql的查詢語(yǔ)法;由于半結(jié)構(gòu)化數(shù)據(jù)中存在多值域,定義“any”、“all”和路徑表達(dá)式解決查詢過(guò)程中的數(shù)據(jù)歧義性的問(wèn)題;7,基于半結(jié)構(gòu)化數(shù)據(jù)中簡(jiǎn)單路徑的優(yōu)化;簡(jiǎn)單路徑是指從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)上最多只存在一個(gè)多值域。本發(fā)明發(fā)現(xiàn)常見(jiàn)的半結(jié)構(gòu)化數(shù)據(jù)中存在大量這樣的結(jié)構(gòu),提出并實(shí)現(xiàn)了針對(duì)這樣結(jié)構(gòu)的存儲(chǔ)和查詢優(yōu)化,極大的提高了查詢的效率。如附圖4所示,本發(fā)明使用不同大小的數(shù)據(jù)集進(jìn)行了數(shù)據(jù)已經(jīng)加載到內(nèi)存中(hotcached)和數(shù)據(jù)還沒(méi)有加載到內(nèi)存中(coldcached)的查詢分析實(shí)驗(yàn)。實(shí)驗(yàn)中,本發(fā)明使用不同的sql查詢語(yǔ)句以得到相應(yīng)的運(yùn)算操作的性能對(duì)比,包括project映射,filter過(guò)濾,group分組,sort排序和join連接操作。根據(jù)圖4所示的查詢性能,在coldcached數(shù)據(jù)沒(méi)有加載到內(nèi)存的實(shí)驗(yàn)中,steed相對(duì)于hive+parquet有4.1到17.8倍的性能加速比,相對(duì)于mongodb有55.9到105.2倍的加速比,相對(duì)于postgresql有33.8到1294倍的加速比;而在hotcached的實(shí)驗(yàn)中,steed對(duì)mongodb有19.5到59.3倍的加速比,對(duì)hive+parquet有19.5到59.3倍的加速比,對(duì)postgresql有16.9到392倍的加速比。附錄中詳細(xì)列出了本發(fā)明的各個(gè)查詢操作的查詢語(yǔ)句。附圖說(shuō)明圖1微博api定義的json數(shù)據(jù)格式分析;圖2apachehadoop通信協(xié)議的相關(guān)分析;圖3是steed的組成模塊圖;圖4是steed的查詢性能對(duì)比圖;圖5是protocolbuffers建立語(yǔ)法樹(shù)的過(guò)程圖;圖6是行式數(shù)據(jù)復(fù)合類型結(jié)構(gòu)示意圖;圖7是列式數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)示意圖;圖8是列式數(shù)據(jù)優(yōu)化存儲(chǔ)結(jié)構(gòu)示意圖;圖9是steed各查詢操作示意圖;圖10是分組操作運(yùn)算過(guò)程中存儲(chǔ)結(jié)構(gòu)示意圖;圖11是經(jīng)過(guò)優(yōu)化的行式存儲(chǔ)結(jié)構(gòu)示意圖;圖12是可供選擇的行式存儲(chǔ)結(jié)構(gòu)的優(yōu)化方案示意圖。具體實(shí)施方式鑒于以上現(xiàn)有技術(shù)的不足,本發(fā)明重新設(shè)計(jì)并實(shí)現(xiàn)了一個(gè)半結(jié)構(gòu)化數(shù)據(jù)處理系統(tǒng)steed。以下介紹了steed系統(tǒng)的整體架構(gòu)并簡(jiǎn)要介紹每一個(gè)模塊的功能需求,之后分析這幾個(gè)模塊間的接口定義,同時(shí)簡(jiǎn)要說(shuō)明steed內(nèi)部是如何處理和存儲(chǔ)數(shù)據(jù)。如圖3所示,steed主要由三個(gè)模塊構(gòu)成:(1)數(shù)據(jù)解析模塊:讀取文本數(shù)據(jù),并將其解析為行式或者列式的二進(jìn)制格式數(shù)據(jù),存儲(chǔ)在數(shù)據(jù)存儲(chǔ)模塊中。在數(shù)據(jù)解析的過(guò)程中,動(dòng)態(tài)生成語(yǔ)法樹(shù),存儲(chǔ)半結(jié)構(gòu)化數(shù)據(jù)的定義。對(duì)json格式的數(shù)據(jù)進(jìn)行解析時(shí),由于其沒(méi)有定義相應(yīng)的數(shù)據(jù)格式(語(yǔ)法樹(shù),schematree),所以本發(fā)明只能在解析數(shù)據(jù)的過(guò)程中動(dòng)態(tài)生成數(shù)據(jù)格式的定義;而對(duì)protocolbuffers格式的數(shù)據(jù),文本格式的數(shù)據(jù)和數(shù)據(jù)相關(guān)的定義會(huì)在數(shù)據(jù)解析前一同被提供,所以本發(fā)明在解析文本格式的數(shù)據(jù)前可以根據(jù)其定義建立語(yǔ)法樹(shù)。根據(jù)語(yǔ)法樹(shù)中域的定義,本發(fā)明將文本結(jié)構(gòu)的數(shù)據(jù)轉(zhuǎn)化為行式及列式的二進(jìn)制格式數(shù)據(jù)。(2)數(shù)據(jù)存儲(chǔ)模塊:存儲(chǔ)了經(jīng)過(guò)數(shù)據(jù)解析模塊生成的行式及列式二進(jìn)制文件。其在內(nèi)部可以實(shí)現(xiàn)對(duì)這兩種格式數(shù)據(jù)的相互轉(zhuǎn)換,以及將其直接輸出為文本格式的json數(shù)據(jù)。在steed系統(tǒng)中,本發(fā)明還根據(jù)行式和列式數(shù)據(jù)存儲(chǔ)的特點(diǎn)對(duì)其存儲(chǔ)結(jié)構(gòu)進(jìn)行了一定的優(yōu)化,使之能夠有較高的存儲(chǔ)和查詢效率。(3)查詢分析模塊:基于行式及列式格式的數(shù)據(jù),對(duì)半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行查詢操作,包括projector映射,filter過(guò)濾,group分組,sort排序和join連接等。當(dāng)steed需要執(zhí)行一次查詢時(shí),先由queryparser查詢解析器根據(jù)查詢語(yǔ)句中的內(nèi)容生成此次查詢所需建立的操作樹(shù)(operatortree),樹(shù)中的每一個(gè)節(jié)點(diǎn)都是一個(gè)sql操作。數(shù)據(jù)在操作樹(shù)中按照從葉子到根節(jié)點(diǎn)的順序完成各個(gè)部分的運(yùn)算直至到達(dá)根節(jié)點(diǎn)完成此次查詢操作。本發(fā)明還實(shí)現(xiàn)了一些操作的多線程版本,支持projector映射,filter過(guò)濾和group分組等操作。steed系統(tǒng)一共分為三個(gè)模塊,接下來(lái)本發(fā)明將逐一介紹每個(gè)模塊的實(shí)現(xiàn)細(xì)節(jié)和過(guò)程。第1部分?jǐn)?shù)據(jù)解析模塊這一部分詳細(xì)介紹了steed的數(shù)據(jù)解析模塊的實(shí)現(xiàn)細(xì)節(jié)和內(nèi)部的關(guān)鍵算法,同時(shí)根據(jù)半結(jié)構(gòu)化數(shù)據(jù)的結(jié)構(gòu)特點(diǎn),說(shuō)明了steed是如何分別針對(duì)json和protocolbuffers解析并建立語(yǔ)法樹(shù)的過(guò)程。1.1數(shù)據(jù)解析模塊結(jié)構(gòu)概述數(shù)據(jù)解析模塊主要由以下三部分構(gòu)成:(1)datatype數(shù)據(jù)類型:用于描述和定義json和protocolbuffers文本數(shù)據(jù)中域的二進(jìn)制數(shù)據(jù)類型。steed系統(tǒng)中定義了一些基本的數(shù)據(jù)類型,例如int,double,string等。對(duì)于json格式的數(shù)據(jù),只需要將文本數(shù)據(jù)的值映射到系統(tǒng)內(nèi)部的數(shù)據(jù)類型即可;而對(duì)于protocolbuffers而言,使用其schema定義的數(shù)據(jù)復(fù)合數(shù)據(jù)類型對(duì)steed默認(rèn)的數(shù)據(jù)類型進(jìn)行相應(yīng)的轉(zhuǎn)換,以供稍后建立語(yǔ)法樹(shù)的過(guò)程使用。(2)schematree數(shù)據(jù)語(yǔ)法樹(shù):建立半結(jié)構(gòu)化數(shù)據(jù)的定義,既語(yǔ)法樹(shù)。對(duì)于protocolbuffers的文本數(shù)據(jù),在解析數(shù)據(jù)前首先根據(jù)其schema定義文件中對(duì)schema定義動(dòng)態(tài)生成語(yǔ)法樹(shù)。在數(shù)據(jù)解析過(guò)程中,定義的語(yǔ)法樹(shù)的內(nèi)容和結(jié)構(gòu)保持不變。json格式的數(shù)據(jù)則需要本發(fā)明在數(shù)據(jù)解析的過(guò)程中根據(jù)其數(shù)據(jù)中的格式和內(nèi)容動(dòng)態(tài)生成此語(yǔ)法樹(shù)的定義。本發(fā)明假設(shè)每個(gè)域中數(shù)值的類型都保持不變,同時(shí)數(shù)組中的每個(gè)元素的值的類型都是相同的。steed存儲(chǔ)了每個(gè)數(shù)據(jù)集對(duì)應(yīng)的語(yǔ)法樹(shù)定義。在查詢分析模塊中,steed將按照語(yǔ)法樹(shù)中數(shù)據(jù)的定義對(duì)數(shù)據(jù)集進(jìn)行相應(yīng)的查詢操作。(3)parser:用于將文本格式的半結(jié)構(gòu)化數(shù)據(jù)拆分成為鍵值對(duì)(keyvaluepairs)的形式,并稍后解析成steed內(nèi)部定義的行式或者列式的存儲(chǔ)結(jié)構(gòu)。對(duì)于protocolbuffers數(shù)據(jù),在解析的過(guò)程只需要按照語(yǔ)法樹(shù)的定義對(duì)數(shù)據(jù)進(jìn)行格式的轉(zhuǎn)換;而對(duì)于json格式的數(shù)據(jù),本發(fā)明在解析的過(guò)程中還需要分析數(shù)據(jù)中是否出現(xiàn)新定義的域,進(jìn)而對(duì)現(xiàn)有的語(yǔ)法樹(shù)進(jìn)行修改。1.2datatype類型1.2.1steed支持的基本數(shù)據(jù)類型steed系統(tǒng)內(nèi)部定義了一些二進(jìn)制格式的數(shù)據(jù),用于行式和列式格式數(shù)據(jù)的存儲(chǔ)和運(yùn)算:1)整形數(shù):typeint(8/16/32/64)分別表示8/16/32/64位的整形數(shù);2)浮點(diǎn)數(shù):type(float/double)分別表示float和double類型的浮點(diǎn)數(shù);3)字符串:typestring表示的字符串;4)時(shí)間戳:typetimestamp表示時(shí)間戳,內(nèi)部用typeint64具體實(shí)現(xiàn)。以上的這些數(shù)據(jù)類型均可支持對(duì)其值的判空,本文和二進(jìn)制數(shù)據(jù)的相互轉(zhuǎn)化,比較操作等。1.2.2json數(shù)據(jù)類型的轉(zhuǎn)化json定義了其數(shù)據(jù)中每個(gè)域中數(shù)據(jù)可能的類型。本發(fā)明將其定義的每個(gè)數(shù)據(jù)類型映射成steed的對(duì)應(yīng)的內(nèi)部數(shù)據(jù)類型,如下表所示:對(duì)于基本的數(shù)據(jù)類型,直接將json定義的類型映射成為steed內(nèi)部的基本數(shù)據(jù)類型;而對(duì)于json中object和array這些嵌套的復(fù)雜數(shù)據(jù)類型,steed內(nèi)部也定義了其對(duì)應(yīng)的行列存儲(chǔ)的方式,具體的存儲(chǔ)方式請(qǐng)見(jiàn)下一章數(shù)據(jù)存儲(chǔ)模塊。1.2.3protocolbuffers數(shù)據(jù)類型的轉(zhuǎn)化與json相似,protocolbuffers也定義一些內(nèi)部基本的數(shù)據(jù)類型。在steed的內(nèi)部實(shí)現(xiàn)中,本發(fā)明直接將這些基本的數(shù)據(jù)類型轉(zhuǎn)化為c++中的類型(c++type),并將其值存儲(chǔ)在解析后的結(jié)果中。參見(jiàn)https://developers.google.com/protocol-buffers/docs/proto3#scalar。此外,protocolbuffers的schema中還可以定義復(fù)合的數(shù)據(jù)類型message。使用復(fù)合數(shù)據(jù)類型,本發(fā)明可以定義多層嵌套的數(shù)據(jù)格式定義。同時(shí),在復(fù)合類型的定義中,本發(fā)明可以選擇域的賦值屬性,既required一定會(huì)出現(xiàn)的域,optional可能會(huì)出現(xiàn)的域和repeated會(huì)重復(fù)出現(xiàn)的域。1.3語(yǔ)法樹(shù)(schematree)在這一小節(jié)中,本發(fā)明將介紹steed是如何使用語(yǔ)法樹(shù)(schematree)描述半結(jié)構(gòu)化數(shù)據(jù)的。同時(shí)還會(huì)介紹在解析過(guò)程中是如何針對(duì)json和protocolbuffers的數(shù)據(jù)以及結(jié)構(gòu)特點(diǎn)建立語(yǔ)法的。1.3.1語(yǔ)法樹(shù)的定義半結(jié)構(gòu)化數(shù)據(jù)存在以下一些結(jié)構(gòu)特點(diǎn):1)數(shù)據(jù)中存在大量的嵌套結(jié)構(gòu):每個(gè)域的定義是有深度的,和傳統(tǒng)的關(guān)系型扁平的數(shù)據(jù)相比更加的復(fù)雜;2)數(shù)據(jù)中的很多多值域:在一條記錄中,可能會(huì)有很多個(gè)值對(duì)其中的某個(gè)域進(jìn)行復(fù)制。3)數(shù)據(jù)中存在大量的稀疏域:大量的域在大部分的數(shù)據(jù)中并沒(méi)有被賦值,而使用傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)以表的方式對(duì)其進(jìn)行處理會(huì)使得存儲(chǔ)和查詢十分的低效。為了能夠高效的描述半結(jié)構(gòu)化數(shù)據(jù)中每個(gè)域的以上特點(diǎn),同時(shí)提高行式和列式的存儲(chǔ)以及查詢效率,本發(fā)明按照如下的定義了填充半結(jié)構(gòu)化數(shù)據(jù)中語(yǔ)法樹(shù)的每一個(gè)節(jié)點(diǎn):節(jié)點(diǎn)中不但描述了節(jié)點(diǎn)本身的相關(guān)信息:數(shù)據(jù)類型,嵌套層次和域中可能被賦值的個(gè)數(shù)等;還通過(guò)schemanode語(yǔ)法節(jié)點(diǎn)id將節(jié)點(diǎn)相互的關(guān)聯(lián),形成樹(shù)型結(jié)構(gòu)。接下來(lái)本發(fā)明將分別介紹如何在解析過(guò)程中為json和protocolbuffers分別建立語(yǔ)法樹(shù)。1.3.1json語(yǔ)法樹(shù)的建立由于json并沒(méi)有數(shù)據(jù)相關(guān)的定義,所以本發(fā)明只能在解析數(shù)據(jù)的過(guò)程中通過(guò)數(shù)據(jù)動(dòng)態(tài)的建立語(yǔ)法樹(shù)。在這里,本發(fā)明假設(shè)每個(gè)域的值的類型是不會(huì)改變的且數(shù)組中的成員類型都是一致的。在建立語(yǔ)法樹(shù)的過(guò)程中,本發(fā)明只需要根據(jù)數(shù)據(jù)中值的類型確定其值的類型。另一方面。由于json數(shù)據(jù)中的每個(gè)域在記錄中是否出現(xiàn)都是不確定的,所以本發(fā)明將值為array的json的域定義為repeated重復(fù)出現(xiàn)的,其余節(jié)點(diǎn)均定義為optional不一定會(huì)出現(xiàn)。在解析過(guò)程中,steed需要先根據(jù)parent父親節(jié)點(diǎn)id和fieldname對(duì)應(yīng)的域名通過(guò)符號(hào)表查找有無(wú)相關(guān)的結(jié)構(gòu)定義。如果沒(méi)有這個(gè)節(jié)點(diǎn)的定義,則向schematree語(yǔ)法樹(shù)中添加相關(guān)的節(jié)點(diǎn);否則則對(duì)這個(gè)節(jié)點(diǎn)的值進(jìn)行解析,詳細(xì)的解析過(guò)程請(qǐng)見(jiàn)下一小節(jié)。1.3.2protocolbuffers語(yǔ)法樹(shù)的建立,如圖5所示:如下例所示,protocolbuffers在proto文件中會(huì)定義message作為新的數(shù)據(jù)類型。其中包含的每個(gè)域既可以是基本的數(shù)據(jù)類型,也可以是其他的復(fù)合類型的數(shù)據(jù)。本發(fā)明在建樹(shù)的過(guò)程中,首先解析proto文件,擴(kuò)展新的數(shù)據(jù)類型;之后再按照用戶指定的根節(jié)點(diǎn)(root)將這些數(shù)據(jù)類型的定義逐一擴(kuò)展并組裝成為數(shù)據(jù)結(jié)構(gòu)的語(yǔ)法樹(shù)(schematree)。之后本發(fā)明就可以按照語(yǔ)法樹(shù)的定義逐一對(duì)每一條文本數(shù)據(jù)進(jìn)行解析。1.4數(shù)據(jù)解析在這一小節(jié)中,本發(fā)明將介紹steed的數(shù)據(jù)解析算法。這里本發(fā)明忽略了系統(tǒng)中許多底層基礎(chǔ)類的實(shí)現(xiàn),僅列出了和文本格式數(shù)據(jù)解析相關(guān)的算法。由于半結(jié)構(gòu)化數(shù)據(jù)分別定義了兩種復(fù)合的數(shù)據(jù)結(jié)構(gòu),既對(duì)象(object)和數(shù)組(array),所以在解析的過(guò)程中,本發(fā)明對(duì)這兩種不同的復(fù)合結(jié)構(gòu)使用不同的方法對(duì)其分別進(jìn)行解析。另一方面,對(duì)于行式和列式二進(jìn)制數(shù)據(jù)的輸出,json和protocolbuffers在本發(fā)明實(shí)現(xiàn)的過(guò)程中是一致的,所以接下來(lái)本發(fā)明首先分別介紹在json和protocolbuffers的解析算法,再說(shuō)明稍后是如何將其數(shù)據(jù)輸出為二進(jìn)制行式和列式的數(shù)據(jù)。1.4.1json數(shù)據(jù)解析過(guò)程算法如下的算法所示,本發(fā)明這里對(duì)原子數(shù)據(jù)類型和復(fù)合數(shù)據(jù)類型采用不同的策略進(jìn)行解析:對(duì)于原子類型的數(shù)據(jù),本發(fā)明直接根據(jù)其文本格式的值轉(zhuǎn)化為二進(jìn)制格式的數(shù)據(jù)進(jìn)行存儲(chǔ)或輸出;對(duì)于復(fù)合結(jié)構(gòu)的數(shù)據(jù),本發(fā)明需要分析并解析其結(jié)構(gòu)直至所有的孩子域都是原子數(shù)據(jù)類型。之后再按照其行式或者列式的存儲(chǔ)結(jié)構(gòu)將其寫入到存儲(chǔ)文件中。對(duì)json文本格式的數(shù)據(jù)解析過(guò)程中,本發(fā)明需要對(duì)每一個(gè)域進(jìn)行比對(duì),判斷其是否是新增的節(jié)點(diǎn),進(jìn)而修改既有的語(yǔ)法樹(shù)。對(duì)于半結(jié)構(gòu)化數(shù)據(jù)中的嵌套結(jié)構(gòu)(上文本框左部分),首先將同層的域拆分成為“鍵值對(duì)”的形式,之后再按照每個(gè)鍵值對(duì)分別進(jìn)行分析。之后分析每個(gè)鍵的定義是否曾經(jīng)出現(xiàn)過(guò),若沒(méi)有出現(xiàn)則更新相應(yīng)的schematree,同時(shí)在schematree中記錄對(duì)應(yīng)域的值。之后按照schematree中每個(gè)節(jié)點(diǎn)記錄的值遞歸進(jìn)行解析:如果是復(fù)合的數(shù)據(jù)類型,則調(diào)用相應(yīng)的復(fù)合結(jié)構(gòu)解析函數(shù)繼續(xù)解析;如果是簡(jiǎn)單類型的值,則直接將其輸出到最后的結(jié)果中去。而對(duì)于多值域的數(shù)組(上文本框右部分),由于其表示同一個(gè)域的多個(gè)重復(fù)出現(xiàn)的值,所以本發(fā)明僅需要依次調(diào)用相應(yīng)的解析函數(shù)對(duì)其內(nèi)容進(jìn)行解析而不用分析其對(duì)schematree的修改。1.4.2protocolbuffers數(shù)據(jù)解析過(guò)程算法對(duì)于protocolbuffers格式的數(shù)據(jù)而言,文本格式數(shù)據(jù)的解析過(guò)程相對(duì)于protocolbuffers更加簡(jiǎn)單:由于其在數(shù)據(jù)解析之前已經(jīng)定義了數(shù)據(jù)的格式,所以本發(fā)明在解析的過(guò)程中不需要檢查和修改語(yǔ)法樹(shù),僅需要對(duì)記錄中每個(gè)域的值分別進(jìn)行解析即可。具體的解析方法和json類似:復(fù)合類型調(diào)用相應(yīng)的解析函數(shù)進(jìn)行解析;簡(jiǎn)單類型則直接將其值輸出到結(jié)果中。1.4.3行式和列式數(shù)據(jù)的輸出算法在解析的過(guò)程中,steed可以將數(shù)據(jù)解析成為行式或者列式的二進(jìn)制格式。這里本發(fā)明將介紹其輸出為行式或列式格式數(shù)據(jù)的具體過(guò)程:(1)行式復(fù)合類型數(shù)據(jù)輸出算法:如以上算法所示,對(duì)于object和array的復(fù)合數(shù)據(jù)類型,行式結(jié)構(gòu)的數(shù)據(jù)分別使用其行式結(jié)構(gòu)的對(duì)象對(duì)每一個(gè)域的值進(jìn)行添加直至整條記錄完成了解析。(2)列式復(fù)合類型數(shù)據(jù)輸出算法:相對(duì)于行式結(jié)構(gòu)的數(shù)據(jù)文件輸出,列式結(jié)構(gòu)數(shù)據(jù)輸出的過(guò)程中僅需要將其葉子節(jié)點(diǎn)上具體的值及其結(jié)構(gòu)信息直接輸出到文件中。所以在解析的過(guò)程中,本發(fā)明不需要保留語(yǔ)義上的的object和array的結(jié)構(gòu),僅記錄其結(jié)構(gòu)相關(guān)信息并輸出到列式存儲(chǔ)的文件中。這樣就會(huì)使得輸出二進(jìn)制格式的過(guò)程相對(duì)簡(jiǎn)單和高效。第2部分?jǐn)?shù)據(jù)存儲(chǔ)模塊在數(shù)據(jù)解析模塊完成數(shù)據(jù)行式或者列式的解析后,數(shù)據(jù)存儲(chǔ)模塊對(duì)解析的結(jié)果進(jìn)行存儲(chǔ)和一定的結(jié)構(gòu)轉(zhuǎn)換,如行式和列式格式的相互轉(zhuǎn)換,將二進(jìn)制格式的數(shù)據(jù)直接以文本格式進(jìn)行輸出等。在這一章中,本發(fā)明首先介紹和行式和列式二進(jìn)制數(shù)據(jù)的底層存儲(chǔ)結(jié)構(gòu)。之后,基于googledremel的組裝算法,本發(fā)明還將說(shuō)明steed是如何實(shí)現(xiàn)列式結(jié)構(gòu)的數(shù)據(jù)轉(zhuǎn)化為行式結(jié)構(gòu)數(shù)據(jù)的組裝算法。2.1行式存儲(chǔ)結(jié)構(gòu)概述在前一章解析過(guò)程的描述中,本發(fā)明使用原子類型的二進(jìn)制格式對(duì)其數(shù)據(jù)進(jìn)行存儲(chǔ);而另兩種復(fù)合結(jié)構(gòu)object對(duì)象和array數(shù)組,本發(fā)明則按照如圖6的方法格式進(jìn)行存儲(chǔ):行式和列式的存儲(chǔ)結(jié)構(gòu)比較類似,主要由以下的幾部分組成:(1)headerinformation結(jié)構(gòu)頭信息:記錄這個(gè)存儲(chǔ)結(jié)構(gòu)的相關(guān)信息,如存儲(chǔ)結(jié)構(gòu)的大小,其中包含的元素個(gè)數(shù)等。(2)(id)offsetarrayid和偏移量數(shù)組:對(duì)于object對(duì)象而言,本發(fā)明需要標(biāo)記其中每個(gè)域的id用于表示其值的存在;而對(duì)于array數(shù)組,其中的每個(gè)值都是相同的域的賦值,所以其僅保留了每個(gè)值的offset偏移量信息。(3)valuearray數(shù)值的數(shù)組:行式的存儲(chǔ)結(jié)構(gòu)都將values重復(fù)出現(xiàn)的數(shù)值存儲(chǔ)為數(shù)組的形式進(jìn)行存儲(chǔ),其中值的類型既可以是原子類型的數(shù)據(jù),也可以是復(fù)合類型的數(shù)據(jù)。在object對(duì)象中,由于表示的是不同域的賦值,所以每個(gè)值的類型可以不相同;但在array數(shù)組中,表示的是相同域的多個(gè)賦值,所以這里本發(fā)明默認(rèn)每個(gè)值的類型都是相同的。根據(jù)之前每個(gè)值的offset偏移量信息,本發(fā)明可以對(duì)任意的域的值進(jìn)行隨機(jī)訪問(wèn)。2.2列式存儲(chǔ)結(jié)構(gòu)概述列式存儲(chǔ)結(jié)構(gòu)相對(duì)于行式結(jié)構(gòu)相對(duì)復(fù)雜,本發(fā)明定義了如下的相關(guān)概念用于在列式結(jié)構(gòu)上表示并存儲(chǔ)其結(jié)構(gòu)信息:(1)repetitionlevel:repeatedvaluerepeatatwhichfieldinthefield’spath.數(shù)據(jù)中的重復(fù)是在哪一個(gè)層次上進(jìn)行的重復(fù)。(2)definitionlevel:numberoffieldinthepathcouldbeundefinedbutpresent.數(shù)據(jù)中可以省略的域(optional和repeated)有幾層是出現(xiàn)的。關(guān)于列式結(jié)構(gòu)的數(shù)據(jù)如何使用這些相關(guān)的信息進(jìn)行列式到行式數(shù)據(jù)轉(zhuǎn)換的過(guò)程詳解下一小節(jié),這里本發(fā)明僅介紹其在行式結(jié)構(gòu)數(shù)據(jù)中的存儲(chǔ)結(jié)構(gòu)。cab(columnalignblock)是本發(fā)明列式存儲(chǔ)的基本單元。在解析過(guò)程中,每個(gè)值(value)都會(huì)產(chǎn)生一條columnitem(列數(shù)據(jù)項(xiàng))存儲(chǔ)在cab中。因?yàn)榘虢Y(jié)構(gòu)化數(shù)據(jù)中會(huì)有很多重復(fù)的域,每個(gè)重復(fù)的域可能會(huì)導(dǎo)致一條記錄中會(huì)有多條columnitem插入到cab中。本發(fā)明為了提高存儲(chǔ)和查詢的效率,對(duì)cab使用recordid對(duì)齊的方式進(jìn)行存儲(chǔ),每個(gè)cab都存儲(chǔ)相同多的record記錄而不考慮具體的columnitem的條數(shù)。圖7中列出了cab的具體的結(jié)構(gòu)圖。主要由以下四部分構(gòu)成:(1)header頭信息:用于描述cab的相關(guān)信息,包括其大小和存儲(chǔ)的記錄條數(shù)等。(2)repetitionarray數(shù)組:用于記錄每條columnitem的repetition值。因?yàn)閞epetition的最大值為每個(gè)域的最大深度,所以這里本發(fā)明使用若干bit代替整數(shù)來(lái)存儲(chǔ)其值。通過(guò)對(duì)數(shù)據(jù)內(nèi)容的分析,本發(fā)明總結(jié)了以下幾種template來(lái)對(duì)其可能出現(xiàn)的模式進(jìn)行總結(jié)和優(yōu)化,如圖8所示。a)nonerepeated非重復(fù)的域:嵌套層次中沒(méi)有可以重復(fù)的域,記錄中這個(gè)域最多只有一個(gè)值,既沒(méi)有重復(fù)賦值的情況。steed在解析的過(guò)程中如果某些域沒(méi)有值時(shí)會(huì)插入null使得每條記錄能夠自然對(duì)齊。這樣,每條記錄有且只有一條columnitem在對(duì)應(yīng)的列式數(shù)據(jù)文件中。因此,本發(fā)明在存儲(chǔ)結(jié)構(gòu)中省略了這個(gè)數(shù)組。b)singlerepeated只會(huì)在某個(gè)嵌套層次進(jìn)行重復(fù):嵌套層次中有且僅有一個(gè)可以重復(fù)的層次。本發(fā)明僅需要標(biāo)記每條記錄的第一條columnitem(recordboundary)。所以本發(fā)明僅需要1bit去標(biāo)記每條記錄的第一條columnitem或者其唯一重復(fù)的嵌套層次。c)multirepeated會(huì)在多個(gè)嵌套層次進(jìn)行重復(fù):如果從根到葉子節(jié)點(diǎn)中存在多個(gè)可以重復(fù)的域,本發(fā)明就需要多個(gè)比特指出其重復(fù)的域。在對(duì)數(shù)據(jù)進(jìn)行了具體的分析后,本發(fā)明發(fā)現(xiàn)絕大部分的域都是最多只會(huì)在一層上重復(fù)。所以通過(guò)使用這3個(gè)template模板進(jìn)行存儲(chǔ),本發(fā)明的列式存儲(chǔ)結(jié)構(gòu)提高了存儲(chǔ)和操作的效率。(3)valuearea數(shù)值區(qū)域:這一部分記錄了全部columnitem的值。對(duì)于變長(zhǎng)和定長(zhǎng)的兩種數(shù)據(jù)格式,本發(fā)明使用了兩種不同的存儲(chǔ)策略:a)定長(zhǎng)的數(shù)據(jù)類型:每個(gè)數(shù)據(jù)的長(zhǎng)度一樣,所以本發(fā)明在header中記錄了每個(gè)值所占用的空間,每次只需要移動(dòng)固定的長(zhǎng)度即可讀取下一個(gè)數(shù)值;不需要額外的offset數(shù)組。b)變長(zhǎng)的數(shù)據(jù)類型:每個(gè)數(shù)據(jù)的長(zhǎng)度不一樣,所以本發(fā)明需要在offset數(shù)組中記錄每個(gè)值的存儲(chǔ)位置;對(duì)于值的內(nèi)容大量重復(fù)的域(例如用戶語(yǔ)言等),我們僅存儲(chǔ)一個(gè)具體的變長(zhǎng)值,通過(guò)在不同的columnitem中復(fù)用該具體值的offset提高其存儲(chǔ)的效率。2.3行式和列式格式轉(zhuǎn)換算法在這一部分中本發(fā)明將介紹在存儲(chǔ)模塊行式和列式文件相互轉(zhuǎn)化的算法。對(duì)于行式數(shù)據(jù)文件而言,每一個(gè)半結(jié)構(gòu)化數(shù)據(jù)集在解析完成之后都會(huì)生成一個(gè)行式數(shù)據(jù)文件存儲(chǔ)所有記錄中的全部域值和相關(guān)的結(jié)構(gòu)信息。另一方面,對(duì)于列式數(shù)據(jù)文件而言,每個(gè)文本數(shù)據(jù)集會(huì)產(chǎn)生若干個(gè)列式存儲(chǔ)文件。每個(gè)域都會(huì)產(chǎn)生一個(gè)列式存儲(chǔ)文件存儲(chǔ)全部記錄的這個(gè)域的所有的值。這樣在運(yùn)行過(guò)程中,存儲(chǔ)模塊就需要實(shí)現(xiàn)存儲(chǔ)數(shù)據(jù)的行列格式轉(zhuǎn)換操作。同時(shí),也需要實(shí)現(xiàn)滿足直接將數(shù)據(jù)輸出為json文本格式的需求。2.3.1行式到列式的數(shù)據(jù)解析行式結(jié)構(gòu)數(shù)據(jù)到列式結(jié)構(gòu)數(shù)據(jù)的轉(zhuǎn)換過(guò)程與文本結(jié)構(gòu)數(shù)據(jù)解析的過(guò)程相似,這里不再贅述。由于在解析過(guò)程中不需要對(duì)文本數(shù)據(jù)的結(jié)構(gòu)進(jìn)行字符的匹配,而使用已經(jīng)解析好的行式的object或array的存儲(chǔ)結(jié)構(gòu);同時(shí)不需要進(jìn)行文本格式數(shù)據(jù)到二進(jìn)制的格式轉(zhuǎn)換,行式到列式結(jié)構(gòu)轉(zhuǎn)換的效率要明顯優(yōu)于字符解析的效率。2.3.2列式到行式的數(shù)據(jù)組裝將列式數(shù)據(jù)文件按照一定的規(guī)則組裝成行式格式的文件就可以完成列式結(jié)構(gòu)的數(shù)據(jù)轉(zhuǎn)化為行式結(jié)構(gòu)的數(shù)據(jù)?;趃oogledremel的組裝算法,這里本發(fā)明在steed內(nèi)部使用類似的算法完成對(duì)列式文件的組裝。具體算法如下所示:在組裝過(guò)程中,steed按照有限狀態(tài)自動(dòng)機(jī)的順序和columnitem中的repetitionvalue從columnreader(列式數(shù)據(jù)讀取器)中讀取columnitem,之后再根據(jù)definitionvalue判斷并輸出相應(yīng)的嵌套層次信息。當(dāng)讀取的最后一個(gè)columnreader讀完本條記錄的最后一個(gè)columnitem時(shí),既遍歷完成所有的columnreader,assembler組裝器就完成了一條記錄的組裝。assembler組裝器會(huì)不斷的運(yùn)行,直到所有的記錄都完成組裝,此時(shí)所有的columnreader都應(yīng)讀取到文件結(jié)尾eof。在以下的算法中,除了具體的組裝過(guò)程assemblerecd,move和return兩個(gè)函數(shù)分別使用definitionvalue判斷數(shù)據(jù)的嵌套層次的結(jié)構(gòu)信息。在如下的偽代碼中,本發(fā)明需要從根節(jié)點(diǎn)開(kāi)始使用深度優(yōu)先算法遍歷schematree,之后按照其葉子節(jié)點(diǎn)出現(xiàn)的順序?qū)α惺轿募M(jìn)行排序,按照排序后的順序依次讀取各個(gè)列式文件中columnitem的內(nèi)容。根據(jù)讀取的的columnitem的內(nèi)容,本發(fā)明可以控制數(shù)據(jù)嵌套的層次結(jié)構(gòu)信息:首先輸出當(dāng)前列中表示嵌套結(jié)構(gòu)的相關(guān)信息,之后將值輸出到待組裝的行式結(jié)構(gòu)中,然后再判斷要跳轉(zhuǎn)并讀取的下一個(gè)列文件,最后從下一列中預(yù)讀一條columnitem判斷需要返回的嵌套層次的層次并輸出相關(guān)的結(jié)構(gòu)信息。當(dāng)所有的列式文件都至少完成一次的讀取后,本發(fā)明就完成了一條記錄的組裝。重復(fù)以上的過(guò)程,直到所有的列式文件都讀完,本發(fā)明就完成了對(duì)整個(gè)數(shù)據(jù)集合的組裝。第3部分查詢分析模塊基于行式和列式結(jié)構(gòu)的數(shù)據(jù),steed可以進(jìn)行類似于sql的查詢分析。但是相比于傳統(tǒng)的表結(jié)構(gòu)的關(guān)系型數(shù)據(jù),半結(jié)構(gòu)化數(shù)據(jù)的由于其存在嵌套和多值域而導(dǎo)致其在查詢時(shí)會(huì)存在一定的歧義。為此本發(fā)明擴(kuò)展了查詢的語(yǔ)法,使其在一定程度上能夠消除數(shù)據(jù)歧義。本發(fā)明還實(shí)現(xiàn)了sql中一些基本的運(yùn)算,如projector映射,filter過(guò)濾,groupby分組和sort排序等。在本章中,本發(fā)明首先介紹針對(duì)半結(jié)構(gòu)化數(shù)據(jù)的擴(kuò)展后的語(yǔ)義。之后,針對(duì)系統(tǒng)中已經(jīng)實(shí)現(xiàn)的多種半結(jié)構(gòu)化數(shù)據(jù)的運(yùn)算,本發(fā)明會(huì)依次介紹其實(shí)現(xiàn)的具體算法。3.1sql針對(duì)半結(jié)構(gòu)化數(shù)據(jù)的語(yǔ)義擴(kuò)展傳統(tǒng)的關(guān)系型數(shù)據(jù)使用表結(jié)構(gòu)存儲(chǔ)扁平的數(shù)據(jù):所有的值都在同一層,不存在嵌套子結(jié)構(gòu);每個(gè)域有且只有一個(gè)數(shù)值能給其賦值;在設(shè)計(jì)表時(shí)會(huì)拆分表,使其不會(huì)存在大量的稀疏的域。而對(duì)于半結(jié)構(gòu)化數(shù)據(jù)而言,其以上的這些特點(diǎn)都不適用。而為了支持半結(jié)構(gòu)化數(shù)據(jù)的操作,本發(fā)明新定義了如下的一些運(yùn)算符:(1)“.”:用于間隔域的路徑表達(dá)式中的嵌套層次。(2)“any”:表示重復(fù)的域中任意的一個(gè)數(shù)值;(3)“all”:表示重復(fù)的域中所有的數(shù)值。輸出的結(jié)果本發(fā)明有多重的選項(xiàng):(1)json格式的數(shù)據(jù):(2)忽略嵌套結(jié)構(gòu)的類json數(shù)據(jù);3.2steed支持的運(yùn)算類型如圖9所示,steed支持基于行式和列式數(shù)據(jù)的多種類型的運(yùn)算。在各個(gè)operator之間,數(shù)據(jù)使用pull的方式依次流動(dòng),直到在頂層的outputoperator完成從二進(jìn)制的到文本格式數(shù)據(jù)的轉(zhuǎn)換。接下來(lái),本發(fā)明會(huì)依次介紹其內(nèi)部的各種實(shí)現(xiàn)細(xì)節(jié)。3.2.1rowfromoperator(行式數(shù)據(jù)讀取運(yùn)算)steed從行式的數(shù)據(jù)文件中讀取一整條行式結(jié)構(gòu)的數(shù)據(jù)。由于每一條記錄在行式數(shù)據(jù)文件中是按照記錄為單位進(jìn)行的存儲(chǔ),每條記錄都是以rowobject行式對(duì)象為存儲(chǔ)的格式進(jìn)行存儲(chǔ)的。所以在讀取記錄時(shí),本發(fā)明每次都從行式二進(jìn)制數(shù)據(jù)文件中讀取一個(gè)rowobject行式對(duì)象依次進(jìn)行讀取,直到到達(dá)文件結(jié)尾eof。3.2.2schemafilter(whereorhavingclause)operator(基于schema定義的where和having字句中的過(guò)濾運(yùn)算)在這個(gè)operator中,本發(fā)明對(duì)行式數(shù)據(jù)進(jìn)行filter過(guò)濾操作。這個(gè)操作可以用于steed在讀取行式數(shù)據(jù)之后,對(duì)其進(jìn)行where字句中的條件進(jìn)行判斷;而在groupby字句中生成新的行式的數(shù)據(jù)之后,也可以使用其對(duì)aggregation聚集的結(jié)果進(jìn)行過(guò)濾操作。在具體的filter過(guò)濾操作過(guò)程中,本發(fā)明定義了rowcondition(行式條件類)用于判斷記錄中相關(guān)的域是否滿足每一個(gè)謂詞(predicate)的條件。具體的判斷過(guò)程如下所示:本發(fā)明首先對(duì)where字句進(jìn)行解析,將每一個(gè)謂詞實(shí)例化為可以進(jìn)行數(shù)據(jù)比較的對(duì)象:可以從行式數(shù)據(jù)結(jié)構(gòu)中讀取數(shù)據(jù);之后對(duì)讀取的值進(jìn)行比較,判斷每個(gè)謂詞(predicate)的真值,決定其是否通過(guò)這個(gè)operator中的條件運(yùn)算。3.2.3projectoperator(映射運(yùn)算)在行式結(jié)構(gòu)的數(shù)據(jù)中本發(fā)明存儲(chǔ)了每條記錄中所有的域,但是大部分的查詢語(yǔ)句僅需要一些域的值即可。這樣在整個(gè)的查詢過(guò)程中,就會(huì)有大量的于查詢無(wú)關(guān)的域的數(shù)據(jù)在各operator運(yùn)算間拷貝了多次。這些額外的內(nèi)存拷貝會(huì)降低本發(fā)明查詢的效率。所以本發(fā)明對(duì)行式結(jié)構(gòu)的數(shù)據(jù)實(shí)現(xiàn)了projector運(yùn)算用于提取和查詢相關(guān)的域,這樣在拷貝過(guò)程中僅拷貝了查詢相關(guān)的域從而提高了查詢的效率。在運(yùn)算過(guò)程中,本發(fā)明使用調(diào)用遞歸函數(shù)應(yīng)對(duì)半結(jié)構(gòu)化數(shù)據(jù)中的嵌套結(jié)構(gòu)。在每一個(gè)域中,本發(fā)明分別讀取原數(shù)據(jù)中該域的賦值,對(duì)其進(jìn)行解析之后僅將和查詢相關(guān)的域?qū)懭氲竭\(yùn)算的結(jié)果中。這樣就能忽略行式數(shù)據(jù)中大量的無(wú)關(guān)的域,提高查詢過(guò)程的效率。對(duì)于多值域,如果其在葉子節(jié)點(diǎn)重復(fù),steed僅需要直接拷貝這個(gè)域的數(shù)組中連續(xù)存儲(chǔ)的多個(gè)值。如果在非葉子節(jié)點(diǎn)重復(fù),則對(duì)以每一個(gè)數(shù)組中的子結(jié)構(gòu)分別遞歸及解析。需要注意的是,在提取子樹(shù)的過(guò)程中,本發(fā)明僅保留了被賦值的子樹(shù);既,如果這個(gè)子樹(shù)中的相關(guān)的域沒(méi)有被賦值,則在projector的結(jié)果中這個(gè)子樹(shù)將不會(huì)被保留。3.2.4assembleoperator(列式到行式數(shù)據(jù)的組裝運(yùn)算)在這個(gè)operator運(yùn)算過(guò)程中,steed完成了將查詢相關(guān)的域從行式結(jié)構(gòu)數(shù)據(jù)轉(zhuǎn)化為列式結(jié)構(gòu)數(shù)據(jù)的組裝過(guò)程。具體的組裝算法請(qǐng)見(jiàn)之前。steed首先通過(guò)queryparser查詢語(yǔ)句解析器解析需要執(zhí)行的sql語(yǔ)句得到所有和查詢相關(guān)的域,使用其建立一個(gè)有限狀態(tài)自動(dòng)機(jī)(fsm)以控制在組裝過(guò)程中行式結(jié)構(gòu)數(shù)據(jù)的讀取順序。之后按照先前的組裝算法完成從列式到行數(shù)數(shù)據(jù)的格式轉(zhuǎn)換,這里不再贅述。3.2.5columnfilteroperator(提供過(guò)濾操作的列式到行式數(shù)據(jù)的組裝運(yùn)算)相比于assembleroperator(列式到行式數(shù)據(jù)的組裝運(yùn)算),columnfilteroperator(提供過(guò)濾操作的列式到行式數(shù)據(jù)的組裝運(yùn)算)不但實(shí)現(xiàn)了列式結(jié)構(gòu)到行式結(jié)構(gòu)的組裝,還能在組裝過(guò)程中對(duì)每個(gè)記錄進(jìn)行filter過(guò)濾操作。由于在查詢過(guò)程中,where子句會(huì)過(guò)濾掉一些不滿足條件的記錄,所以如果本發(fā)明在組裝過(guò)程中不組裝這些無(wú)效的記錄,會(huì)極大的提高查詢效率。所以在查詢過(guò)程中,本發(fā)明每次讀取一個(gè)cab進(jìn)行filter過(guò)濾操作并設(shè)立相應(yīng)的bitmap位圖記錄其比較的結(jié)果,最后根據(jù)記錄的結(jié)果中再?zèng)Q定是否進(jìn)行組裝。3.2.6joinoperator(連接運(yùn)算)steed中使用hashjoin(哈希連接)實(shí)現(xiàn)連接操作,現(xiàn)階段僅支持兩個(gè)表的連接操作。在執(zhí)行這個(gè)操作的過(guò)程中,steed根據(jù)其中一個(gè)數(shù)據(jù)集記錄中的joinkey具體值計(jì)算其對(duì)應(yīng)的哈希值并將整條記錄存儲(chǔ)在哈希表中。稍后遍歷另一個(gè)數(shù)據(jù)集合,查找具有相同hashkey哈希鍵的對(duì)應(yīng)哈希表中的位置(bucket)。之后將這兩個(gè)行式結(jié)構(gòu)的數(shù)據(jù)進(jìn)行合并,并等待這條記錄被pull(拉)到上一層的operator運(yùn)算?,F(xiàn)階段steed并沒(méi)有使用關(guān)系型數(shù)據(jù)庫(kù)中查詢優(yōu)化器進(jìn)行優(yōu)化,故而在查詢過(guò)程中建議將較小的數(shù)據(jù)集作為from子句中第一個(gè)出現(xiàn)的數(shù)據(jù)集,以得到較高的存儲(chǔ)效率。3.2.7groupoperator(分組運(yùn)算)在查詢操作現(xiàn)階段所支持的內(nèi)部操作中,group分組是最復(fù)雜的操作。本發(fā)明將會(huì)介紹在運(yùn)算過(guò)程中一些新定義的類,并對(duì)相應(yīng)的執(zhí)行過(guò)程進(jìn)行分析。和joinoperator連接操作類似,groupoperator分組操作使用hashtable哈希表存儲(chǔ)相應(yīng)的groupkey分組的鍵值。在運(yùn)算的過(guò)程中,首先由從行式結(jié)構(gòu)的數(shù)據(jù)中讀取數(shù)據(jù),計(jì)算其hashkey哈希值并添加到哈希表中。之后再根據(jù)需要判斷其有無(wú)aggregation聚集運(yùn)算對(duì)hashvalue哈希值中的內(nèi)容進(jìn)行運(yùn)算。其中hashvalue哈希值的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)如圖10所示:本發(fā)明首先定義了hashvalueitemcontainer用于存儲(chǔ)每個(gè)在哈希表中的每一個(gè)存儲(chǔ)單元(bucket),哈希表中具體的value值為指向這些hashvalueitem的地址。每個(gè)這樣的對(duì)象都有如圖10所示的結(jié)構(gòu):(1)本發(fā)明首先在中間層保存記錄存儲(chǔ)的具體地址和每個(gè)需要計(jì)算的aggregation聚集的內(nèi)容。(2)在blockbuffer對(duì)象中,存儲(chǔ)了被保存的記錄的實(shí)際內(nèi)容。需要指出的是,這些記錄除了那些groupedfield基于值進(jìn)行分組的域,都是沒(méi)有被賦值的表示aggregation聚集結(jié)果的域。當(dāng)整個(gè)group分組運(yùn)算完成之后,本發(fā)明再將aggregation聚集的結(jié)果輸入到相應(yīng)的位置,并等待結(jié)果被上層的其他operator操作pull拉起。3.2.8orderoperator(排序操作)對(duì)于orderby排序操作運(yùn)算,本發(fā)明需要將所有的記錄存儲(chǔ)到buffer緩存中,之后對(duì)其比較排序??紤]到內(nèi)存空間分配效率的問(wèn)題,本發(fā)明每次僅向操作系統(tǒng)申請(qǐng)固定大小的內(nèi)存,這樣可以省去realloc重新分配內(nèi)存中過(guò)程中內(nèi)存拷貝的代價(jià)。同時(shí),為了避免在排序過(guò)程中多次拷貝數(shù)據(jù)的代價(jià),本發(fā)明在比較過(guò)程中使用一個(gè)數(shù)組記錄每條記錄的起始地址并在排序過(guò)程中改變指針在數(shù)組中的位置。最終達(dá)到對(duì)這個(gè)數(shù)組順序訪問(wèn)時(shí),訪問(wèn)到的記錄都是滿足排序要求的結(jié)果。此外根據(jù)排序的條件,本發(fā)明定義了comparer比較器用比較記錄,其按照如下的方式進(jìn)行運(yùn)算:(1)這個(gè)comparer比較器可以從行式存儲(chǔ)結(jié)構(gòu)中讀取所有域的數(shù)值用于比較操作。(2)為了提高比較效率,本發(fā)明如下實(shí)現(xiàn)了比較及輸出的過(guò)程:a)在每條記錄中保留了8字節(jié)存儲(chǔ)第一個(gè)需要比較的域中數(shù)據(jù)的高8位。對(duì)于所有的數(shù)值類型而言,這個(gè)空間足以存儲(chǔ)其對(duì)應(yīng)的值而不需要復(fù)雜的對(duì)行式結(jié)構(gòu)的數(shù)據(jù)進(jìn)行取值;對(duì)于字符串而言,前8位的比較在大多數(shù)情況下也能得到確定的比較結(jié)果。所以在比較過(guò)程中,本發(fā)明先使用緩存的這8字節(jié)進(jìn)行比較。當(dāng)數(shù)據(jù)的類型為字符串且前綴的比較相同時(shí),本發(fā)明才會(huì)進(jìn)行下一步比較。b)使用comparer比較器根據(jù)需要排序的域的順序,依次取值并進(jìn)行排序,直到得到比較的結(jié)果。c)具體的比較函數(shù)的實(shí)現(xiàn)本發(fā)明使用stl::sort函數(shù)進(jìn)行比較。d)在比較過(guò)程中沒(méi)有對(duì)記錄的本身進(jìn)行數(shù)據(jù)拷貝,只修改了記錄輸出順序的指針數(shù)組,這樣避免了內(nèi)存的多次拷貝操作。而在被上層operator操作pull拉數(shù)據(jù)的過(guò)程中,本發(fā)明也僅提供了對(duì)應(yīng)的指針,以提高其數(shù)據(jù)處理的效率。第4部分利用簡(jiǎn)單路徑特征優(yōu)化樹(shù)狀結(jié)構(gòu)數(shù)據(jù)的方法及系統(tǒng)在這一部分中,本發(fā)明根據(jù)現(xiàn)有多種數(shù)據(jù)來(lái)源的相關(guān)數(shù)據(jù),總結(jié)并歸納出了簡(jiǎn)單路徑的概念,并且在steed中利用該特征進(jìn)行了查詢優(yōu)化4.1簡(jiǎn)單路徑的定義在分析了多種不同來(lái)源的數(shù)據(jù),我們發(fā)現(xiàn)在各數(shù)據(jù)集的語(yǔ)法樹(shù)中,存在著大量的從根到葉子節(jié)點(diǎn)最多只有一個(gè)重復(fù)域的路徑。本發(fā)明在查詢的過(guò)程中可以利用這些數(shù)據(jù)中的結(jié)構(gòu)特點(diǎn)優(yōu)化查詢過(guò)程、提高查詢效率。所以,本發(fā)明對(duì)簡(jiǎn)單路徑定義如下:在數(shù)據(jù)集的語(yǔ)法樹(shù)中,從根到葉子節(jié)點(diǎn)的路徑上最多只能存在一個(gè)域(語(yǔ)法樹(shù)中的某個(gè)節(jié)點(diǎn))是多值的,我們稱這樣的路徑為簡(jiǎn)單路徑。steed中可以利用簡(jiǎn)單路徑對(duì)樹(shù)狀結(jié)構(gòu)數(shù)據(jù)進(jìn)行存儲(chǔ)及查詢過(guò)程相關(guān)的優(yōu)化。4.2半結(jié)構(gòu)化數(shù)據(jù)行式存儲(chǔ)的結(jié)構(gòu)如前所述,steed在行式存儲(chǔ)結(jié)構(gòu)中為了準(zhǔn)確表達(dá)樹(shù)狀結(jié)構(gòu)數(shù)據(jù)中的層次信息使用了相對(duì)復(fù)雜存儲(chǔ)結(jié)構(gòu)。經(jīng)過(guò)分析,本發(fā)明認(rèn)為從數(shù)據(jù)的表達(dá)上看,已經(jīng)不能對(duì)其進(jìn)行進(jìn)一步的優(yōu)化和改進(jìn)。但是通過(guò)以上簡(jiǎn)單路徑的分析可知,本發(fā)明可以通過(guò)簡(jiǎn)化數(shù)據(jù)中存儲(chǔ)的結(jié)構(gòu)信息以提高數(shù)據(jù)在系統(tǒng)內(nèi)部的表示效率,使得其解析和查詢的效率有進(jìn)一步的提升。本發(fā)明設(shè)想的更好的行式存儲(chǔ)結(jié)構(gòu)如圖11所示:對(duì)于簡(jiǎn)單路徑的數(shù)據(jù),steed可以在數(shù)據(jù)中僅存儲(chǔ)葉子節(jié)點(diǎn)(域)的相關(guān)結(jié)構(gòu)信息來(lái)代替原有的嵌套存儲(chǔ)結(jié)構(gòu)來(lái)指代相應(yīng)的路徑。而使用簡(jiǎn)單路徑進(jìn)行優(yōu)化之后,steed可以利用數(shù)據(jù)中葉子節(jié)點(diǎn)的相關(guān)信息從系統(tǒng)中的語(yǔ)法樹(shù)(schematree)獲得整個(gè)路徑上所有節(jié)點(diǎn)的相關(guān)信息。這樣,steed通過(guò)簡(jiǎn)化數(shù)據(jù)中存儲(chǔ)的結(jié)構(gòu)信息提高了行式數(shù)據(jù)的表達(dá)效率和查詢的執(zhí)行效率。4.3flattenassemble(扁平行式結(jié)構(gòu)組裝器)steed在數(shù)據(jù)的組裝過(guò)程中,需要花費(fèi)大量代價(jià)來(lái)恢復(fù)數(shù)據(jù)的層次結(jié)構(gòu)。如前所述,在大多數(shù)的數(shù)據(jù)集中的域中重復(fù)的層次都不超過(guò)2層,所以數(shù)據(jù)中絕大部分的值都可以利用簡(jiǎn)單路徑進(jìn)行相應(yīng)的優(yōu)化。而steed中對(duì)于簡(jiǎn)單路徑的域的組裝過(guò)程則更加的簡(jiǎn)便:使用flattenassembler扁平行式結(jié)構(gòu)組裝器忽略默認(rèn)二進(jìn)制數(shù)據(jù)中的層次關(guān)系,既僅使用葉子節(jié)點(diǎn)表示從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑而忽略路徑中所有的非葉子節(jié)點(diǎn)。這樣,本發(fā)明就實(shí)現(xiàn)了將行式結(jié)構(gòu)數(shù)據(jù)的嵌套層次限制為一層的目的,從而在數(shù)據(jù)查詢的過(guò)程中節(jié)約了數(shù)據(jù)在內(nèi)存中的空間消耗并且提高了數(shù)據(jù)的查詢效率。具體的組裝算法如上所示:在組裝之前,需要對(duì)待組裝的每一個(gè)列按照葉子節(jié)點(diǎn)的id進(jìn)行相應(yīng)的排序。之后,依次按照順序讀取每個(gè)columnreader中每條記錄的所有columnitem,依次將讀出的數(shù)值和相關(guān)的結(jié)構(gòu)信息寫入到組裝的結(jié)果中去。這里由于組裝的結(jié)果僅保留了一個(gè)嵌套的層次,所以在組裝過(guò)程中steed只需要將每個(gè)域的值追加到當(dāng)前的對(duì)象中,而不需要考慮組裝結(jié)果的嵌套關(guān)系。4.4扁平行式數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)本發(fā)明中,steed在查詢過(guò)程使用扁平結(jié)構(gòu)的行式數(shù)據(jù)進(jìn)行查詢和存儲(chǔ)等方面的優(yōu)化。對(duì)于語(yǔ)法樹(shù)中的非簡(jiǎn)單路徑,由于steed需要識(shí)別數(shù)據(jù)中不同嵌套層次的多值域,本發(fā)明繼續(xù)使用系統(tǒng)默認(rèn)的樹(shù)狀結(jié)構(gòu)數(shù)據(jù)的表達(dá)方法。而對(duì)于簡(jiǎn)單路徑,本發(fā)明使用如圖11的結(jié)構(gòu)對(duì)其進(jìn)行存儲(chǔ)或組裝:1)語(yǔ)法樹(shù)中從根到葉子節(jié)點(diǎn)的路徑上沒(méi)有重復(fù)節(jié)點(diǎn)的域:扁平數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)中僅需要存儲(chǔ)葉子節(jié)點(diǎn)的id和相應(yīng)域的數(shù)值;2)語(yǔ)法樹(shù)中從根到葉子節(jié)點(diǎn)的路徑上只有一個(gè)重復(fù)節(jié)點(diǎn)的域:扁平數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)中可以按照以下兩種結(jié)構(gòu)進(jìn)行輸出,詳見(jiàn)圖12:a)將每個(gè)重復(fù)域的數(shù)值都作為一個(gè)具體的值存儲(chǔ)在扁平結(jié)構(gòu)中----數(shù)據(jù)中會(huì)有多項(xiàng)有相同id的值,其個(gè)數(shù)決定于重復(fù)域的個(gè)數(shù);b)將重復(fù)的域作為一個(gè)整體存儲(chǔ)在扁平結(jié)構(gòu)中----數(shù)據(jù)中僅有一個(gè)重復(fù)域的id表示其具體的值,而這個(gè)域是由一個(gè)數(shù)組形式的結(jié)構(gòu)表示多個(gè)數(shù)值。3)語(yǔ)法樹(shù)從根到葉子節(jié)點(diǎn)的路徑上有多個(gè)重復(fù)的節(jié)點(diǎn):扁平數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)無(wú)法表達(dá)路徑上多個(gè)可重復(fù)的域的數(shù)值是在哪一層上發(fā)生的重復(fù),本發(fā)明中繼續(xù)使用原有的默認(rèn)的樹(shù)狀數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)----扁平結(jié)構(gòu)的數(shù)據(jù)中依然使用葉子節(jié)點(diǎn)的id,但是相應(yīng)的值為偏移量,指向存儲(chǔ)完整嵌套結(jié)構(gòu)的位置。本發(fā)明提出一種利用簡(jiǎn)單路徑特征優(yōu)化樹(shù)狀結(jié)構(gòu)數(shù)據(jù)的系統(tǒng),包括:簡(jiǎn)單路徑模塊,用于設(shè)置簡(jiǎn)單路徑,其中所述簡(jiǎn)單路徑為在數(shù)據(jù)集的語(yǔ)法樹(shù)中,從根節(jié)點(diǎn)到葉子節(jié)點(diǎn),最多只能存在一個(gè)多值的域的路徑;獲取數(shù)據(jù)模塊,用于通過(guò)存儲(chǔ)所述簡(jiǎn)單路徑中葉子節(jié)點(diǎn)的相關(guān)結(jié)構(gòu)信息,獲取原有嵌套存儲(chǔ)結(jié)構(gòu)中的數(shù)據(jù);組裝模塊,用于對(duì)所述簡(jiǎn)單路徑中葉子節(jié)點(diǎn)進(jìn)行組裝,其中忽略默認(rèn)二進(jìn)制數(shù)據(jù)中的層次關(guān)系,僅通過(guò)葉子節(jié)點(diǎn)表示從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑而忽略路徑中所有的非葉子節(jié)點(diǎn)。利用數(shù)據(jù)集中葉子節(jié)點(diǎn)的相關(guān)信息從語(yǔ)法樹(shù)中獲得整個(gè)簡(jiǎn)單路徑上所有節(jié)點(diǎn)的相關(guān)信息。在組裝之前,對(duì)待組裝的每一個(gè)列數(shù)據(jù)按照葉子節(jié)點(diǎn)的id進(jìn)行相應(yīng)的排序,之后,依次按照順序讀取每個(gè)columnreader中每條記錄的所有columnitem,依次將讀出的數(shù)值與相關(guān)的結(jié)構(gòu)信息寫入到組裝的結(jié)果中。對(duì)于語(yǔ)法樹(shù)中的非簡(jiǎn)單路徑,識(shí)別數(shù)據(jù)中各嵌套層次的多值域。本發(fā)明系統(tǒng)使用如圖11的結(jié)構(gòu)進(jìn)行存儲(chǔ)或組裝,具體如下所示:1)當(dāng)語(yǔ)法樹(shù)中從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上沒(méi)有重復(fù)節(jié)點(diǎn)的域:僅需要存儲(chǔ)葉子節(jié)點(diǎn)的id與相應(yīng)域的數(shù)值;2)當(dāng)語(yǔ)法樹(shù)中從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上只有一個(gè)重復(fù)節(jié)點(diǎn)的域:按照以下兩種結(jié)構(gòu)進(jìn)行輸出:a)將每個(gè)重復(fù)域的數(shù)值都作為一個(gè)具體的值存儲(chǔ)在扁平結(jié)構(gòu)中,其中,數(shù)據(jù)中會(huì)有多項(xiàng)有相同id的值,其個(gè)數(shù)決定于重復(fù)域的個(gè)數(shù);b)將重復(fù)的域作為一個(gè)整體存儲(chǔ)在扁平結(jié)構(gòu)中,其中數(shù)據(jù)中僅有一個(gè)重復(fù)域的id表示其具體的值,且所述重復(fù)域是由一個(gè)數(shù)組形式的結(jié)構(gòu)表示多個(gè)數(shù)值;3)語(yǔ)法樹(shù)從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑上有多個(gè)重復(fù)的節(jié)點(diǎn):使用默認(rèn)的樹(shù)狀數(shù)據(jù)存儲(chǔ)結(jié)構(gòu),其中扁平結(jié)構(gòu)的數(shù)據(jù)中依然使用葉子節(jié)點(diǎn)的id,id表示為偏移量,指向存儲(chǔ)完整嵌套結(jié)構(gòu)的位置。當(dāng)前第1頁(yè)12當(dāng)前第1頁(yè)12