您好,登錄后才能下訂單哦!
??由于不同的項(xiàng)目使用不同的詞語(yǔ)描述各種概念,所以這里有一個(gè)小小的術(shù)語(yǔ)表來(lái)幫助消除歧義。
??默認(rèn)情況下,Arrow格式是低位編址的(將低序字節(jié)存儲(chǔ)在起始地址)。模式元數(shù)據(jù)有一個(gè)指明RecordBatches的字節(jié)順序的字段。通常這是生成RecordBatch的系統(tǒng)的字節(jié)順序。主要用例是在具有相同字節(jié)碼的系統(tǒng)之間交換RecordBatches。首先,當(dāng)嘗試讀取與底層系統(tǒng)不匹配的字節(jié)順序的模式時(shí),將會(huì)返回錯(cuò)誤。參考實(shí)現(xiàn)集中在地位編址,并為此提供測(cè)試。最終我們可以通過字節(jié)交換來(lái)提供自動(dòng)轉(zhuǎn)換。
??如上所述,所有緩沖區(qū)都旨在以64字節(jié)邊界為準(zhǔn)對(duì)齊內(nèi)存,并且填充到64字節(jié)倍數(shù)的長(zhǎng)度。對(duì)齊要求遵循優(yōu)化內(nèi)存訪問的最佳做法:
??任何數(shù)組具有已知且固定長(zhǎng)度,存儲(chǔ)為32位有符號(hào)整數(shù),因此最多可以存儲(chǔ)(2^31 - 1)個(gè)元素。我們選擇一個(gè)有符號(hào)的int32有一下2個(gè)原因:
??空值槽的數(shù)量是物理數(shù)組的屬性,并被認(rèn)為是數(shù)據(jù)結(jié)構(gòu)的一部分。空值計(jì)數(shù)存儲(chǔ)為32位有符號(hào)整數(shù),因?yàn)樗赡芘c數(shù)組長(zhǎng)度一樣大。
??任何相對(duì)類型都可以有空值槽,不管是原始類型還是嵌套類型。
??具有空值的數(shù)組必須具有連續(xù)的內(nèi)存緩沖區(qū),稱為空(或有效)位圖,其長(zhǎng)度為64字節(jié)的倍數(shù)(如上所述),并且足夠大,以至于每個(gè)數(shù)組槽至少有1位。
??任何數(shù)組槽是否有效(非空)是在該位圖的各個(gè)位中編碼的。索引(設(shè)置位)j值為1表示該值不為空,而0(位未設(shè)置)表示該值為空。位圖被初始化為在分配時(shí)間全部未設(shè)置(這包括填充)。
is_valid[j] -> bitmap[j / 8] & (1 << (j % 8))
??我們使用最低有效位(LSB)編號(hào)(也稱為位編址bit-endianness)。這意味著在一組8個(gè)位中,我們從右到左讀:
values = [0, 1, null, 2, null, 3]
bitmap
j mod 8 7 6 5 4 3 2 1 0
0 0 1 0 1 0 1 1
??具有0空值計(jì)數(shù)的數(shù)組可以選擇不分配空值位圖。實(shí)現(xiàn)為了方便可能會(huì)選擇始終分配一個(gè)空值位圖,但是在內(nèi)存被共享時(shí)應(yīng)該注意。
??嵌套類型數(shù)組具有自己的空值位圖和空值計(jì)數(shù),而不管其子數(shù)組的空值和空位。
??基本類型值數(shù)組表示固定長(zhǎng)度的數(shù)組,每個(gè)值都具有通常用字節(jié)測(cè)量的相同的物理槽寬度,盡管規(guī)范還提供了位打包類型(例如以位編碼的布爾值)。
??在內(nèi)部,數(shù)組包含一個(gè)連續(xù)的內(nèi)存緩沖區(qū),其總大小等于槽寬乘以數(shù)組長(zhǎng)度。對(duì)于打包類型,大小將舍入到最接近的字節(jié)。
??關(guān)聯(lián)的空值位圖被連續(xù)分配(如上所述),但不需要在內(nèi)存中與值緩沖器相鄰。
例如int32的原始數(shù)組:
[1,2,null,4,8]
會(huì)像:
* Length: 5, Null count: 1
* Null bitmap buffer:
|Byte 0 (validity bitmap) \| Bytes 1-63 |
|-------------------------|-----------------------|
|00011011 | 0 (padding) |
* Value Buffer:
|Bytes 0-3 | Bytes 4-7 | Bytes 8-11| Bytes 12-15| Bytes 16-19 | Bytes 20-63 |
|----------|-----------|-----------|-----------|-------------|-------------|
| 1 | 2 | unspecified| 4 | 8 | unspecified |
[1,2,3,4,8]有兩種可能的布局:
* Length: 5, Null count: 0
* Null bitmap buffer:
| Byte 0 (validity bitmap) | Bytes 1-63 |
|--------------------------|-----------------------|
| 00011111 | 0 (padding) |
* Value Buffer:
|Bytes 0-3 | Bytes 4-7| Bytes 8-11| bytes 12-15 | bytes 16-19 | Bytes 20-63 |
|---------|----------|------------|-------------|-------------|-------------|
| 1 | 2 | 3 | 4 | 8 | unspecified |
或者位圖消失:
* Length 5, Null count: 0
* Null bitmap buffer: Not required
* Value Buffer:
|Bytes 0-3 | Bytes 4-7 | Bytes 8-11| bytes 12-15 | bytes 16-19| Bytes 20-63 |
|---------|-----------|------------|-------------|------------|-------------|
| 1 | 2 | 3 | 4 | 8 | unspecified |
??列表是一種嵌套類型,其中每個(gè)數(shù)組槽都包含一個(gè)可變大小的值序列,它們都具有相同的相對(duì)類型(異質(zhì)性可以通過聯(lián)合實(shí)現(xiàn),稍后描述)。
??列表類型被指定為L(zhǎng)ist<T>,這里的T是任何相對(duì)類型(原始或嵌套)。
??列表數(shù)組由以下組合表示:
slot_position = offsets[j]
slot_length = offsets[j + 1] - offsets[j] // (for 0 <= j < length)
偏移數(shù)組中的第一個(gè)值為0,最后一個(gè)元素是值數(shù)組的長(zhǎng)度。
我們來(lái)看一個(gè)例子,List<Char>類型:其中Char是一個(gè)1字節(jié)的邏輯類型。
對(duì)于具有相應(yīng)值的長(zhǎng)度為4的數(shù)組:
[['j','o','e'],null,['m','a','r','k'],[]]
將具有以下表示:
* Length: 4, Null count: 1
* Null bitmap buffer:
| Byte 0 (validity bitmap) | Bytes 1-63 |
|--------------------------|-----------------------|
| 00001101 | 0 (padding) |
* Offsets buffer (int32)
| Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | Bytes 16-19 | Bytes 20-63 |
|------------|-------------|-------------|-------------|-------------|-------------|
| 0 | 3 | 3 | 7 | 7 | unspecified |
* Values array (char array):
* Length: 7, Null count: 0
* Null bitmap buffer: Not required
| Bytes 0-6 | Bytes 7-63 |
|------------|-------------|
| joemark | unspecified |
[[[1,2],[3,4]],[[5,6,7],null,[8]],[[9,10]]]
將被表示如下:
* Length 3
* Nulls count: 0
* Null bitmap buffer: Not required
* Offsets buffer (int32)
| Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | Bytes 16-63 |
|------------|------------|------------|-------------|-------------|
| 0 | 2 | 5 | 6 | unspecified |
* Values array (`List<byte>`)
* Length: 6, Null count: 1
* Null bitmap buffer:
| Byte 0 (validity bitmap) | Bytes 1-63 |
|--------------------------|-------------|
| 00110111 | 0 (padding) |
* Offsets buffer (int32)
| Bytes 0-27 | Bytes 28-63 |
|----------------------|-------------|
| 0, 2, 4, 7, 7, 8, 10 | unspecified |
* Values array (bytes):
* Length: 10, Null count: 0
* Null bitmap buffer: Not required
| Bytes 0-9 | Bytes 10-63 |
|-------------------------------|-------------|
| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 | unspecified |
一個(gè)struct是一個(gè)嵌套類型,它被一個(gè)有序序列的相對(duì)類型(可以都是不同的)參數(shù)化,相對(duì)類型稱為它的字段。
通常,這些字段具有名稱,但名稱及其類型是元數(shù)據(jù)類型的一部分,而不是物理內(nèi)存布局。
一個(gè)struct數(shù)組沒有為它的值分配任何額外的物理存儲(chǔ)。如果結(jié)構(gòu)體數(shù)組有一個(gè)或多個(gè)空值,則它必須具有分配的空值位圖。
在物理上,一個(gè)struct類型中每個(gè)字段都有一個(gè)子數(shù)組。
例如,struct(這里顯示為字符串的字段名稱用于說明)
Struct <
name: String (= List<char>),
age: Int32
>
有兩個(gè)子數(shù)組,一個(gè)列表 數(shù)組(如上所示)和一個(gè)具有Int32邏輯類型的4字節(jié)的基本類型數(shù)組。
[{'joe',1},{null,2},null,{'mark',4}]的布局將是:
* Length: 4, Null count: 1
* Null bitmap buffer:
|Byte 0 (validity bitmap) | Bytes 1-63 |
|-------------------------|-----------------------|
| 00001011 | 0 (padding) |
* Children arrays:
* field-0 array (`List<char>`):
* Length: 4, Null count: 2
* Null bitmap buffer:
| Byte 0 (validity bitmap) | Bytes 1-63 |
|--------------------------|-----------------------|
| 00001001 | 0 (padding) |
* Offsets buffer:
| Bytes 0-19 |
|----------------|
| 0, 3, 3, 3, 7 |
* Values array:
* Length: 7, Null count: 0
* Null bitmap buffer: Not required
* Value buffer:
| Bytes 0-6 |
|----------------|
| joemark |
* field-1 array (int32 array):
* Length: 4, Null count: 1
* Null bitmap buffer:
| Byte 0 (validity bitmap) | Bytes 1-63 |
|--------------------------|-----------------------|
| 00001011 | 0 (padding) |
* Value Buffer:
|Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | Bytes 16-63 |
|------------|-------------|-------------|-------------|-------------|
| 1 | 2 | unspecified | 4 | unspecified |
雖然結(jié)構(gòu)體沒有為每個(gè)語(yǔ)義槽(即每個(gè)與C語(yǔ)言樣結(jié)構(gòu)體相似的標(biāo)量)提供物理存儲(chǔ),但是可以通過空值位圖將整個(gè)結(jié)構(gòu)化槽設(shè)置為空。任何子字段數(shù)組可以根據(jù)各自的獨(dú)立空值位圖擁有空值。這意味著對(duì)于特定的結(jié)構(gòu)體槽,結(jié)構(gòu)體數(shù)組的空值位圖可能表示一個(gè)空槽,當(dāng)其一個(gè)或多個(gè)子數(shù)組在其相應(yīng)的槽中具有非空值時(shí)。讀取結(jié)構(gòu)體數(shù)組時(shí),父空值位圖是權(quán)威的。這在上面的示例中說明,子數(shù)組具有空值結(jié)構(gòu)體的有效實(shí)體,但是由父數(shù)組的空值位圖“隱藏”。但是,獨(dú)立處理時(shí),子數(shù)組的對(duì)應(yīng)值將不為空。
密集的聯(lián)合在語(yǔ)義上類似于一個(gè)結(jié)構(gòu)體,并且包含相對(duì)類型的有序序列。當(dāng)一個(gè)結(jié)構(gòu)體包含多個(gè)數(shù)組時(shí),一個(gè)聯(lián)合語(yǔ)義上是一個(gè)單個(gè)數(shù)組,其中每個(gè)槽可以有一個(gè)不同的類型。
聯(lián)合類型可以被命名,但是像結(jié)構(gòu)體一樣,這將是元數(shù)據(jù)的問題,并且不會(huì)影響物理內(nèi)存布局。
我們定義了針對(duì)不同用例優(yōu)化的兩種不同的聯(lián)合類型。首先,密集聯(lián)合,表示每個(gè)值為5字節(jié)開銷的混合型數(shù)組。其物理布局如下:
每個(gè)相對(duì)類型一個(gè)子數(shù)組
邏輯聯(lián)合的示例布局: Union<f: float, i: int32>具有以下值:[{f = 1.2},null,{f = 3.4},{i = 5}]
* Length: 4, Null count: 1
* Null bitmap buffer:
|Byte 0 (validity bitmap) | Bytes 1-63 |
|-------------------------|-----------------------|
|00001101 | 0 (padding) |
* Types buffer:
|Byte 0 | Byte 1 | Byte 2 | Byte 3 | Bytes 4-63 |
|---------|-------------|----------|----------|-------------|
| 0 | unspecified | 0 | 1 | unspecified |
//存的是Union中的索引 f索引為0, i索引為1
* Offset buffer:
|Byte 0-3 | Byte 4-7 | Byte 8-11 | Byte 12-15 | Bytes 16-63 |
|---------|-------------|-----------|------------|-------------|
| 0 | unspecified | 1 | 0 | unspecified |
* Children arrays:
* Field-0 array (f: float):
* Length: 2, nulls: 0
* Null bitmap buffer: Not required
* Value Buffer:
| Bytes 0-7 | Bytes 8-63 |
|-----------|-------------|
| 1.2, 3.4 | unspecified |
* Field-1 array (i: int32):
* Length: 1, nulls: 0
* Null bitmap buffer: Not required
* Value Buffer:
| Bytes 0-3 | Bytes 4-63 |
|-----------|-------------|
| 5 | unspecified |
稀疏聯(lián)合與密集聯(lián)合具有相同的結(jié)構(gòu),省略了偏移數(shù)組。在這種情況下,子數(shù)組的長(zhǎng)度與union的長(zhǎng)度相等。
雖然與密集聯(lián)合相比,稀疏聯(lián)合可能使用明顯更多的空間,但在某些確定的用例中可能擁有一些優(yōu)點(diǎn):
對(duì)于聯(lián)合數(shù)組:
[{u0 = 5},{u1 = 1.2},{u2 ='joe'},{u1 = 3.4},{u0 = 4},{u2 ='mark'}]
將具有以下布局:
* Length: 6, Null count: 0
* Null bitmap buffer: Not required
* Types buffer:
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Bytes 6-63 |
|------------|-------------|-------------|-------------|-------------|--------------|-----------------------|
| 0 | 1 | 2 | 1 | 0 | 2 | unspecified (padding) |
* Children arrays:
* u0 (Int32):
* Length: 6, Null count: 4
* Null bitmap buffer:
|Byte 0 (validity bitmap) | Bytes 1-63 |
|-------------------------|-----------------------|
|00010001 | 0 (padding) |
* Value buffer:
|Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | Bytes 16-19 | Bytes 20-23 | Bytes 24-63 |
|------------|-------------|-------------|-------------|-------------|--------------|-----------------------|
| 5 | unspecified | unspecified | unspecified | 4 | unspecified | unspecified (padding) |
* u1 (float):
* Length: 6, Null count: 4
* Null bitmap buffer:
|Byte 0 (validity bitmap) | Bytes 1-63 |
|-------------------------|-----------------------|
| 00001010 | 0 (padding) |
* Value buffer:
|Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | Bytes 16-19 | Bytes 20-23 | Bytes 24-63 |
|-------------|-------------|-------------|-------------|-------------|--------------|-----------------------|
| unspecified | 1.2 | unspecified | 3.4 | unspecified | unspecified | unspecified (padding) |
* u2 (`List<char>`)
* Length: 6, Null count: 4
* Null bitmap buffer:
| Byte 0 (validity bitmap) | Bytes 1-63 |
|--------------------------|-----------------------|
| 00100100 | 0 (padding) |
* Offsets buffer (int32)
| Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | Bytes 16-19 | Bytes 20-23 | Bytes 24-27 | Bytes 28-63 |
|------------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|
| 0 | 0 | 0 | 3 | 3 | 3 | 7 | unspecified |
* Values array (char array):
* Length: 7, Null count: 0
* Null bitmap buffer: Not required
| Bytes 0-7 | Bytes 8-63 |
|------------|-----------------------|
| joemark | unspecified (padding) |
請(qǐng)注意,稀疏聯(lián)合中的嵌套類型必須在內(nèi)部一致(例如,見圖中的列表),即任何子數(shù)組上任何索引j的隨機(jī)訪問都不會(huì)導(dǎo)致錯(cuò)誤。換句話說,嵌套類型的數(shù)組如果被重新解釋為非嵌套數(shù)組,則必須是有效的。
與結(jié)構(gòu)類似,特定的子數(shù)組可能具有非空槽,即使父聯(lián)合數(shù)組的空值位圖表示槽為空。此外,即使類型數(shù)組指示槽在索引處包含不同類型,子數(shù)組也可能具有非空槽。
當(dāng)字段被字典編碼時(shí),這些值由表示字典中值的索引的Int32數(shù)組表示。字典被收錄為DictionaryBatch,它的id由字段表中的元數(shù)據(jù)(Message.fbs)中定義的字典屬性引用。字典具有與字段類型相同的布局。字典中的每個(gè)實(shí)體都可以通過其DictionaryBatch中的索引來(lái)訪問。當(dāng)Schema引用Dictionary id時(shí),它必須在任何RecordBatch之前為此id發(fā)送DictionaryBatch。
例如,您可以獲得以下數(shù)據(jù):
type: List<String>
[
['a', 'b'],
['a', 'b'],
['a', 'b'],
['c', 'd', 'e'],
['c', 'd', 'e'],
['c', 'd', 'e'],
['c', 'd', 'e'],
['a', 'b']
]
在字典編碼的形式中,這可能顯示為:
data List<String> (dictionary-encoded, dictionary id i)
indices: [0, 0, 0, 1, 1, 1, 0]
//['a','b']為字典值,索引為0;['c', 'd', 'e']為字典值,索引為2
dictionary i
type: List<String>
[
['a', 'b'],
['c', 'd', 'e'],
]
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。