欧美在线观看视频网站,亚洲熟妇色自偷自拍另类,啪啪伊人网,中文字幕第13亚洲另类,中文成人久久久久影院免费观看 ,精品人妻人人做人人爽,亚洲a视频

一種樹狀數(shù)據(jù)的行式和列式存儲方法及系統(tǒng)與流程

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