元數據:邏輯類型,模式,數據頭
這是Arrow元數據規範的文檔,它使系統能夠通信
- 邏輯數組類型(使用Layout.md中指定的物理內存佈局實現)
- Arrow數據結構的表格集合的模式
- “數據頭”指明內存緩衝區的物理位置,內存緩衝區不復制內存而足以重建Arrow數據結構。
規範實現
我們正在使用Flatbuffers進行低開銷讀寫Arrow元數據。請參閱Message.fbs。
架構
Schema類型描述了由任意數量的Arrow數組組成的表狀結構,每個Arrow數組可以被解釋爲表中的一列。模式本身不描述任何特定數據集的物理結構。
模式由一系列字段組成,這些字段是描述列的元數據。Flatbuffers IDL的一個字段是:table Field { // Name is not required, in i.e. a List name: string; nullable: bool; type: Type; // present only if the field is dictionary encoded // will point to a dictionary provided by a DictionaryBatch message dictionary: long; // children apply only to Nested data types like Struct, List and Union children: [Field]; /// layout of buffers produced for this type (as derived from the Type) /// does not include children /// each recordbatch will return instances of those Buffers. layout: [ VectorLayout ]; // User-defined metadata custom_metadata: [ KeyValue ]; }
type是字段的邏輯類型。嵌套類型(如List,Struct和Union)具有一系列子字段。
還提供了該模式的JSON表示形式:字段:{ "name" : "name_of_the_field", "nullable" : false, "type" : /* Type */, "children" : [ /* Field */ ], "typeLayout" : { "vectors" : [ /* VectorLayout */ ] } }
VectorLayout:
{
"type" : "DATA|OFFSET|VALIDITY|TYPE",
"typeBitWidth" : /* int */
}
Type:
{
"name" :"null|struct|list|union|int|floatingpoint|utf8|binary|fixedsizebinary|bool|decimal|date|time|timestamp|interval"
// fields as defined in the Flatbuffer depending on the type name
}
Union:
{
"name" : "union",
"mode" : "Sparse|Dense",
"typeIds" : [ /* integer */ ]
}
在Union中的typeIds字段是用於表示每種類型的編碼,其可以與從子數組的索引不同。這樣就可以使用聯合類型ids不需要從0開始枚舉。
Int:
{
"name" : "int",
"bitWidth" : /* integer */,
"isSigned" : /* boolean */
}
FloatingPoint:
{
"name" : "floatingpoint",
"precision" : "HALF|SINGLE|DOUBLE"
}
Decimal:
{
"name" : "decimal",
"precision" : /* integer */,
"scale" : /* integer */
}
Timestamp:
{
"name" : "timestamp",
"unit" : "SECOND|MILLISECOND|MICROSECOND|NANOSECOND"
}
Date:
{
"name" : "date",
"unit" : "DAY|MILLISECOND"
}
Time:
{
"name" : "time",
"unit" : "SECOND|MILLISECOND|MICROSECOND|NANOSECOND",
"bitWidth": /* integer: 32 or 64 */
}
Interval:
{
"name" : "interval",
"unit" : "YEAR_MONTH|DAY_TIME"
}
Schema:
{
"fields" : [
/* Field */
]
}
記錄數據頭
RecordBatch是頂級命名的等長Arrow數組(或向量)的集合。如果其中一個數組包含嵌套數據,則其子數組不需要與頂級數組的長度相同。
可以被認爲是特定模式的實現。描述特定RecordBatch的元數據稱爲“數據頭”。這是用於RecordBatch數據頭的Flatbuffers的IDL
table RecordBatch {
length: long;
nodes: [FieldNode];
buffers: [Buffer];
}
所述RecordBatch元數據提供與長度超過2^31- 1的記錄批次,但Arrow實現不要求實現支持超出這一大小。
通過對給定的內存中數據集的模式(可能包含嵌套類型)進行深度優先遍歷/扁平化,生成nodes和buffers字段。
緩衝區
緩衝區是描述相對於某些虛擬地址空間的連續內存區域的元數據。這可能包括:
- 共享內存,例如內存映射文件
- 在內存中接收到RPC消息
-
文件中的數據
緩衝區類型的鍵形式是:struct Buffer { offset: long; length: long; }
在record batch的上下文中,每個字段具有與其相關聯的一些數量的緩衝區,它們源於其物理內存佈局。
每個邏輯類型(與其子節點分開,如果它是一個嵌套類型)具有與之相關聯的確定性數量的緩衝區。這些將在邏輯類型部分中指定。字段元數據
所述FieldNode值包含關於在嵌套類型層次每個等級的元數據。
struct FieldNode { /// The number of value slots in the Arrow array at this level of a nested /// tree length: long; /// The number of observed nulls. null_count: lohng; }
所述FieldNode元數據提供長度超過2^31- 1的字段,但是Arrow不要求實現支持大型數組。
平鋪嵌套數據
嵌套類型以深度優先順序在record batch中扁平化。當訪問嵌套類型樹中的每個字段時,元數據將附加到頂級fields數組,並將與該字段相關聯的緩衝區(但不是其子級)附加到buffers數組。
例如,讓我們考慮模式:
col1: Struct<a: Int32, b: List<Int64>, c: Float64>
col2: Utf8
其扁平化版本是:
FieldNode 0: Struct name='col1'
FieldNode 1: Int32 name=a'
FieldNode 2: List name='b'
FieldNode 3: Int64 name='item' # arbitrary
FieldNode 4: Float64 name='c'
FieldNode 5: Utf8 name='col2'
對於生成的緩衝區,將具有以下內容(如下面對於每種類型的更詳細描述):
buffer 0: field 0 validity bitmap
buffer 1: field 1 validity bitmap
buffer 2: field 1 values <int32_t*>
buffer 3: field 2 validity bitmap
buffer 4: field 2 list offsets <int32_t*>
buffer 5: field 3 validity bitmap
buffer 6: field 3 values <int64_t*>
buffer 7: field 4 validity bitmap
buffer 8: field 4 values <double*>
buffer 9: field 5 validity bitmap
buffer 10: field 5 offsets <int32_t*>
buffer 11: field 5 data <uint8_t*>
邏輯類型
邏輯類型由類型名稱和元數據以及對物理內存表示的顯式映射組成。這些可能分爲不同的類別:
- 表示爲固定寬度基本類型數組(例如:C風格的整數和浮點數)
- 具有與物理嵌套類型相等的內存佈局的類型(例如,字符串使用列表(List)表示,但邏輯上不是嵌套類型)
整型
在Arrow的第一個版本中,我們提供標準的8位到64位大小的標準C整數類型,包括有符號和無符號:
● 有符號類型:Int8,Int16,Int32,Int64
● 無符號類型:UInt8,UInt16,UInt32,UInt64
IDL看起來像:table Int { bitWidth: int; is_signed: bool; }
整數字節順序當前在模式級別全局設置。如果一個模式設置爲little-endian(低位編址),那麼出現在其中的所有整數類型都必須是little-endian。整數作爲其他數據表示的一部分(如列表偏移量和聯合類型)必須與整個Record Batch具有相同的字節順序。
浮點數字
我們提供3種類型的浮點數作爲固定位寬的基本數組
- 半精度,16位寬
- 單精度,32位寬
- 雙精度,64位寬
IDL與下述類似:
enum Precision:int {HALF, SINGLE, DOUBLE}
table FloatingPoint {
precision: Precision;
}
Boolean
布爾邏輯類型表示爲1位寬的基本(原語)物理類型。這些位使用最低有效位(LSB)排序進行編號。
像其他固定的位寬基本類型一樣,布爾數據在數據頭中顯示爲2個緩衝區(一個位圖爲有效向量,另一個爲值)。
List
List邏輯類型是(和相同名稱)列表物理類型的邏輯對應。
在數據頭格式中,List字段節點包含2個緩衝區:
- 有效位圖
- 列表偏移量
與List的子字段相關聯的緩衝區根據子邏輯類型(例如,List<Utf8>對List<Boolean>)遞歸地處理。Utf8和Binary
我們爲可變長度字節指定兩種邏輯類型:
- Utf8 數據是具有UTF-8編碼的unicode值
- Binary 是任何其他可變長度字節
這些類型都與嵌套類型List<UInt8>具有相同的內存佈局,其約束是內部字節不能包含空值。從邏輯類型的角度來看,它們是原始的,而不是嵌套類型。
在數據頭格式中,雖然List<UInt8>會顯示爲2個字段節點(List 和UInt8)和4個緩衝區(每個節點爲2個,如上所述),這些類型也有簡單的表示單字段節點(Utf8或Binary 邏輯類型,沒有子節點)和3個緩衝區: - 有效位圖
- 列表偏移量
- 字節數據
-
Decimal
TBD
Timestamp
所有時間戳都以64位整數存儲,有四個單位:秒,毫秒,微秒和納秒。
Date
支持兩種不同的日期類型:
- 自UNIX epoch以來的天數爲32位整數
- 從UNIX epoch開始的毫秒數爲64位整數
Time
時間支持相同的單位:秒,毫秒,微秒和納秒。我們將時間表示爲容納指定單位的最小整數。對於秒和毫秒:32位,其他64位。