統計資訊結構描述#

警告

此規範應視為實驗性質。

理由#

統計資訊對於快速查詢處理非常有用。許多查詢引擎使用統計資訊來最佳化其查詢計畫。

Apache Arrow 格式沒有統計資訊,但是可以讀取為 Apache Arrow 資料的其他格式可能具有統計資訊。例如,Apache Parquet C++ 實作可以將 Apache Parquet 檔案讀取為 Apache Arrow 資料,而 Apache Parquet 檔案可能具有統計資訊。

我們將統計資訊的表示方式標準化為 Apache Arrow 陣列,以方便交換。

使用案例#

Arrow C 串流介面 的其中一個使用案例如下

  1. 模組 A 將 Apache Parquet 檔案讀取為 Apache Arrow 資料。

  2. 模組 A 透過 Arrow C 串流介面將讀取的 Apache Arrow 資料傳遞給模組 B。

  3. 模組 B 處理傳遞的 Apache Arrow 資料。

如果模組 A 可以將與 Apache Parquet 檔案相關聯的統計資訊傳遞給模組 B,則模組 B 可以使用這些統計資訊來最佳化其查詢計畫。

例如,DuckDB 使用此方法,但 DuckDB 無法使用統計資訊,因為沒有標準化的方式來表示 Apache Arrow 資料的統計資訊。

目標#

  • 建立將統計資訊表示為 Apache Arrow 陣列的標準方式。

非目標#

  • 建立傳遞代表統計資訊的 Apache Arrow 陣列的標準方式。

  • 建立將統計資訊嵌入到 Apache Arrow 陣列本身的標準方式。

結構描述#

此規範僅提供統計資訊的結構描述。這是將關於 Apache Arrow 資料集的統計資訊表示為 Apache Arrow 資料的標準結構描述。

以下是統計資訊結構描述的概要

struct<
  column: int32,
  statistics: map<
    key: dictionary<values: utf8, indices: int32>,
    items: dense_union<...all needed types...>
  >
>

以下是頂層 struct 的詳細資訊

名稱

資料類型

是否可為 Null

註解

column

int32

true

從零開始的欄索引,如果統計資訊描述的是整個表格或記錄批次,則為 null。

欄索引的計算規則與 RecordBatch 訊息 使用的規則相同。

statistics

map

false

目標欄、表格或記錄批次的統計資訊。詳細資訊請參閱下方的個別表格。

以下是 statisticsmap 的詳細資訊

鍵或項目

資料類型

是否可為 Null

註解

key

dictionary<values: utf8, indices: int32>

false

字串鍵是統計資訊的名稱。字典編碼用於提高效率,因為相同的統計資訊可能會針對不同的欄重複使用。精確值和近似統計資訊值會指派不同的鍵。每個統計資訊在下方都有其描述。

items

dense_union

false

統計資訊值是 dense union。它至少具有基於鍵中統計資訊種類的所有必要類型。例如,當您具有 int64 相異計數統計資訊和 float64 平均位元組寬度統計資訊時,您至少需要 int64float64 類型。請參閱下方每個統計資訊的描述。

Dense union 陣列的每個欄位都有名稱,但我們沒有將這些欄位的欄位名稱標準化,因為我們可以改用類型代碼來存取適當的欄位。因此,我們可以為欄位使用任何有效的名稱。

標準統計資訊#

每種統計資訊種類都有一個名稱,該名稱會作為每個欄或整個表格的統計資訊 map 中的鍵出現。dictionary<values: utf8, indices: int32> 用於編碼名稱以提高空間效率。

我們為相同統計資訊的變體指派不同的名稱,而不是使用旗標。例如,我們為「相異計數」統計資訊的精確值和近似值指派不同的統計資訊名稱。

冒號符號 : 用作命名空間分隔符號,例如 自訂應用程式中繼資料。它可以在名稱中多次使用。

ARROW 字首是此規範目前和未來版本中預先定義的統計資訊名稱的保留命名空間。使用者定義的統計資訊不得使用它。例如,您可以使用您的產品名稱作為命名空間,例如 MY_PRODUCT:my_statistics:exact

以下是預先定義的統計資訊名稱

名稱

資料類型

註解

ARROW:average_byte_width:exact

float64

目標欄中一列的平均大小(以位元組為單位)。(精確)

ARROW:average_byte_width:approximate

float64

目標欄中一列的平均大小(以位元組為單位)。(近似)

ARROW:distinct_count:exact

int64

目標欄中相異值的數量。(精確)

ARROW:distinct_count:approximate

float64

目標欄中相異值的數量。(近似)

ARROW:max_byte_width:exact

int64

目標欄中一列的最大大小(以位元組為單位)。(精確)

ARROW:max_byte_width:approximate

float64

目標欄中一列的最大大小(以位元組為單位)。(近似)

ARROW:max_value:exact

目標相關

目標欄中的最大值。(精確)

ARROW:max_value:approximate

目標相關

目標欄中的最大值。(近似)

ARROW:min_value:exact

目標相關

目標欄中的最小值。(精確)

ARROW:min_value:approximate

目標相關

目標欄中的最小值。(近似)

ARROW:null_count:exact

int64

目標欄中 null 的數量。(精確)

ARROW:null_count:approximate

float64

目標欄中 null 的數量。(近似)

ARROW:row_count:exact

int64

目標表格、記錄批次或陣列中的列數。(精確)

ARROW:row_count:approximate

float64

目標表格、記錄批次或陣列中的列數。(近似)

如果您發現可能有助於多個系統的統計資訊,請在 Apache Arrow 開發郵件論壇 上提出。

當統計資訊的產生者和消費者都遵循先前協議的統計資訊規範時,互通性就會提高。

範例#

以下是一些範例,可幫助您理解。

簡單記錄批次#

結構描述

vendor_id: int32
passenger_count: int64

資料

vendor_id:       [5, 1, 5, 1, 5]
passenger_count: [1, 1, 2, 0, null]

統計資訊

目標

名稱

記錄批次

列數

5

vendor_id

null 的數量

0

vendor_id

相異值的數量

2

vendor_id

最大值

5

vendor_id

最小值

1

passenger_count

null 的數量

1

passenger_count

相異值的數量

3

passenger_count

最大值

2

passenger_count

最小值

0

欄索引

索引

目標

0

vendor_id

1

passenger_count

統計資訊結構描述

struct<
  column: int32,
  statistics: map<
    key: dictionary<values: utf8, indices: int32>,
    items: dense_union<0: int64>
  >
>

統計資訊陣列

column: [
  null, # record batch
  0,    # vendor_id
  0,    # vendor_id
  0,    # vendor_id
  0,    # vendor_id
  1,    # passenger_count
  1,    # passenger_count
  1,    # passenger_count
  1,    # passenger_count
]
statistics:
  key:
    values: [
      "ARROW:row_count:exact",
      "ARROW:null_count:exact",
      "ARROW:distinct_count:exact",
      "ARROW:max_value:exact",
      "ARROW:min_value:exact",
    ],
    indices: [
      0, # "ARROW:row_count:exact"
      1, # "ARROW:null_count:exact"
      2, # "ARROW:distinct_count:exact"
      3, # "ARROW:max_value:exact"
      4, # "ARROW:min_value:exact"
      1, # "ARROW:null_count:exact"
      2, # "ARROW:distinct_count:exact"
      3, # "ARROW:max_value:exact"
      4, # "ARROW:min_value:exact"
    ]
  items:
    children:
      0: [ # int64
        5, # record batch: "ARROW:row_count:exact"
        0, # vendor_id: "ARROW:null_count:exact"
        2, # vendor_id: "ARROW:distinct_count:exact"
        5, # vendor_id: "ARROW:max_value:exact"
        1, # vendor_id: "ARROW:min_value:exact"
        1, # passenger_count: "ARROW:null_count:exact"
        3, # passenger_count: "ARROW:distinct_count:exact"
        2, # passenger_count: "ARROW:max_value:exact"
        0, # passenger_count: "ARROW:min_value:exact"
      ]
    types: [ # all values are int64
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
    ]
    offsets: [
      0,
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
    ]

複雜記錄批次#

這使用巢狀類型。

結構描述

col1: struct<a: int32, b: list<item: int64>, c: float64>
col2: utf8

資料

col1: [
        {a: 1, b: [20, 30, 40], c: 2.9},
        {a: 2, b: null,         c: -2.9},
        {a: 3, b: [99],         c: null},
      ]
col2: ["x", null, "z"]

統計資訊

目標

名稱

記錄批次

列數

3

col1

null 的數量

0

col1.a

null 的數量

0

col1.a

相異值的數量

3

col1.a

近似最大值

5

col1.a

近似最小值

0

col1.b

null 的數量

1

col1.b.item

最大值

99

col1.b.item

最小值

20

col1.c

null 的數量

1

col1.c

近似最大值

3.0

col1.c

近似最小值

-3.0

col2

null 的數量

1

col2

相異值的數量

2

欄索引

索引

目標

0

col1

1

col1.a

2

col1.b

3

col1.b.item

4

col1.c

5

col2

另請參閱 RecordBatch 訊息,了解如何計算欄索引。

統計資訊結構描述

struct<
  column: int32,
  statistics: map<
    key: dictionary<values: utf8, indices: int32>,
    items: dense_union<
      # For the number of rows, the number of nulls and so on.
      0: int64,
      # For the max/min values of col1.c.
      1: float64
    >
  >
>

統計資訊陣列

column: [
  null, # record batch
  0,    # col1
  1,    # col1.a
  1,    # col1.a
  1,    # col1.a
  1,    # col1.a
  2,    # col1.b
  3,    # col1.b.item
  3,    # col1.b.item
  4,    # col1.c
  4,    # col1.c
  4,    # col1.c
  5,    # col2
  5,    # col2
]
statistics:
  key:
    values: [
      "ARROW:row_count:exact",
      "ARROW:null_count:exact",
      "ARROW:distinct_count:exact",
      "ARROW:max_value:approximate",
      "ARROW:min_value:approximate",
      "ARROW:max_value:exact",
      "ARROW:min_value:exact",
    ]
    indices: [
      0, # "ARROW:row_count:exact"
      1, # "ARROW:null_count:exact"
      1, # "ARROW:null_count:exact"
      2, # "ARROW:distinct_count:exact"
      3, # "ARROW:max_value:approximate"
      4, # "ARROW:min_value:approximate"
      1, # "ARROW:null_count:exact"
      5, # "ARROW:max_value:exact"
      6, # "ARROW:min_value:exact"
      1, # "ARROW:null_count:exact"
      3, # "ARROW:max_value:approximate"
      4, # "ARROW:min_value:approximate"
      1, # "ARROW:null_count:exact"
      2, # "ARROW:distinct_count:exact"
    ]
  items:
    children:
      0: [ # int64
        3,  # record batch: "ARROW:row_count:exact"
        0,  # col1: "ARROW:null_count:exact"
        0,  # col1.a: "ARROW:null_count:exact"
        3,  # col1.a: "ARROW:distinct_count:exact"
        5,  # col1.a: "ARROW:max_value:approximate"
        0,  # col1.a: "ARROW:min_value:approximate"
        1,  # col1.b: "ARROW:null_count:exact"
        99, # col1.b.item: "ARROW:max_value:exact"
        20, # col1.b.item: "ARROW:min_value:exact"
        1,  # col1.c: "ARROW:null_count:exact"
        1,  # col2: "ARROW:null_count:exact"
        2,  # col2: "ARROW:distinct_count:exact"
      ]
      1: [ # float64
        3.0,  # col1.c: "ARROW:max_value:approximate"
        -3.0, # col1.c: "ARROW:min_value:approximate"
      ]
    types: [
      0, # int64: record batch: "ARROW:row_count:exact"
      0, # int64: col1: "ARROW:null_count:exact"
      0, # int64: col1.a: "ARROW:null_count:exact"
      0, # int64: col1.a: "ARROW:distinct_count:exact"
      0, # int64: col1.a: "ARROW:max_value:approximate"
      0, # int64: col1.a: "ARROW:min_value:approximate"
      0, # int64: col1.b: "ARROW:null_count:exact"
      0, # int64: col1.b.item: "ARROW:max_value:exact"
      0, # int64: col1.b.item: "ARROW:min_value:exact"
      0, # int64: col1.c: "ARROW:null_count:exact"
      1, # float64: col1.c: "ARROW:max_value:approximate"
      1, # float64: col1.c: "ARROW:min_value:approximate"
      0, # int64: col2: "ARROW:null_count:exact"
      0, # int64: col2: "ARROW:distinct_count:exact"
    ]
    offsets: [
      0,  # int64: record batch: "ARROW:row_count:exact"
      1,  # int64: col1: "ARROW:null_count:exact"
      2,  # int64: col1.a: "ARROW:null_count:exact"
      3,  # int64: col1.a: "ARROW:distinct_count:exact"
      4,  # int64: col1.a: "ARROW:max_value:approximate"
      5,  # int64: col1.a: "ARROW:min_value:approximate"
      6,  # int64: col1.b: "ARROW:null_count:exact"
      7,  # int64: col1.b.item: "ARROW:max_value:exact"
      8,  # int64: col1.b.item: "ARROW:min_value:exact"
      9,  # int64: col1.c: "ARROW:null_count:exact"
      0,  # float64: col1.c: "ARROW:max_value:approximate"
      1,  # float64: col1.c: "ARROW:min_value:approximate"
      10, # int64: col2: "ARROW:null_count:exact"
      11, # int64: col2: "ARROW:distinct_count:exact"
    ]

簡單陣列#

結構描述

int64

資料

[1, 1, 2, 0, null]

統計資訊

目標

名稱

陣列

列數

5

陣列

null 的數量

1

陣列

相異值的數量

3

陣列

最大值

2

陣列

最小值

0

欄索引

索引

目標

0

陣列

統計資訊結構描述

struct<
  column: int32,
  statistics: map<
    key: dictionary<values: utf8, indices: int32>,
    items: dense_union<0: int64>
  >
>

統計資訊陣列

column: [
  0, # array
  0, # array
  0, # array
  0, # array
  0, # array
]
statistics:
  key:
    values: [
      "ARROW:row_count:exact",
      "ARROW:null_count:exact",
      "ARROW:distinct_count:exact",
      "ARROW:max_value:exact",
      "ARROW:min_value:exact",
    ]
    indices: [
      0, # "ARROW:row_count:exact"
      1, # "ARROW:null_count:exact"
      2, # "ARROW:distinct_count:exact"
      3, # "ARROW:max_value:exact"
      4, # "ARROW:min_value:exact"
    ]
  items:
    children:
      0: [ # int64
        5, # array: "ARROW:row_count:exact"
        1, # array: "ARROW:null_count:exact"
        3, # array: "ARROW:distinct_count:exact"
        2, # array: "ARROW:max_value:exact"
        0, # array: "ARROW:min_value:exact"
      ]
    types: [ # all values are int64
      0,
      0,
      0,
      0,
      0,
    ]
    offsets: [
      0,
      1,
      2,
      3,
      4,
    ]

複雜陣列#

這使用巢狀類型。

結構描述

struct<a: int32, b: list<item: int64>, c: float64>

資料

[
  {a: 1, b: [20, 30, 40], c: 2.9},
  {a: 2, b: null,         c: -2.9},
  {a: 3, b: [99],         c: null},
]

統計資訊

目標

名稱

陣列

列數

3

陣列

null 的數量

0

a

null 的數量

0

a

相異值的數量

3

a

近似最大值

5

a

近似最小值

0

b

null 的數量

1

b.item

最大值

99

b.item

最小值

20

c

null 的數量

1

c

近似最大值

3.0

c

近似最小值

-3.0

欄索引

索引

目標

0

陣列

1

a

2

b

3

b.item

4

c

另請參閱 RecordBatch 訊息,了解如何計算欄索引。

統計資訊結構描述

struct<
  column: int32,
  statistics: map<
    key: dictionary<values: utf8, indices: int32>,
    items: dense_union<
      # For the number of rows, the number of nulls and so on.
      0: int64,
      # For the max/min values of c.
      1: float64
    >
  >
>

統計資訊陣列

column: [
  0, # array
  0, # array
  1, # a
  1, # a
  1, # a
  1, # a
  2, # b
  3, # b.item
  3, # b.item
  4, # c
  4, # c
  4, # c
]
statistics:
  key:
    values: [
      "ARROW:row_count:exact",
      "ARROW:null_count:exact",
      "ARROW:distinct_count:exact",
      "ARROW:max_value:approximate",
      "ARROW:min_value:approximate",
      "ARROW:max_value:exact",
      "ARROW:min_value:exact",
    ]
    indices: [
      0, # "ARROW:row_count:exact"
      1, # "ARROW:null_count:exact"
      1, # "ARROW:null_count:exact"
      2, # "ARROW:distinct_count:exact"
      3, # "ARROW:max_value:approximate"
      4, # "ARROW:min_value:approximate"
      1, # "ARROW:null_count:exact"
      5, # "ARROW:max_value:exact"
      6, # "ARROW:min_value:exact"
      1, # "ARROW:null_count:exact"
      3, # "ARROW:max_value:approximate"
      4, # "ARROW:min_value:approximate"
    ]
  items:
    children:
      0: [ # int64
        3,  # array: "ARROW:row_count:exact"
        0,  # array: "ARROW:null_count:exact"
        0,  # a: "ARROW:null_count:exact"
        3,  # a: "ARROW:distinct_count:exact"
        5,  # a: "ARROW:max_value:approximate"
        0,  # a: "ARROW:min_value:approximate"
        1,  # b: "ARROW:null_count:exact"
        99, # b.item: "ARROW:max_value:exact"
        20, # b.item: "ARROW:min_value:exact"
        1,  # c: "ARROW:null_count:exact"
      ]
      1: [ # float64
        3.0,  # c: "ARROW:max_value:approximate"
        -3.0, # c: "ARROW:min_value:approximate"
      ]
    types: [
      0, # int64: array: "ARROW:row_count:exact"
      0, # int64: array: "ARROW:null_count:exact"
      0, # int64: a: "ARROW:null_count:exact"
      0, # int64: a: "ARROW:distinct_count:exact"
      0, # int64: a: "ARROW:max_value:approximate"
      0, # int64: a: "ARROW:min_value:approximate"
      0, # int64: b: "ARROW:null_count:exact"
      0, # int64: b.item: "ARROW:max_value:exact"
      0, # int64: b.item: "ARROW:min_value:exact"
      0, # int64: c: "ARROW:null_count:exact"
      1, # float64: c: "ARROW:max_value:approximate"
      1, # float64: c: "ARROW:min_value:approximate"
    ]
    offsets: [
      0, # int64: array: "ARROW:row_count:exact"
      1, # int64: array: "ARROW:null_count:exact"
      2, # int64: a: "ARROW:null_count:exact"
      3, # int64: a: "ARROW:distinct_count:exact"
      4, # int64: a: "ARROW:max_value:approximate"
      5, # int64: a: "ARROW:min_value:approximate"
      6, # int64: b: "ARROW:null_count:exact"
      7, # int64: b.item: "ARROW:max_value:exact"
      8, # int64: b.item: "ARROW:min_value:exact"
      9, # int64: c: "ARROW:null_count:exact"
      0, # float64: c: "ARROW:max_value:approximate"
      1, # float64: c: "ARROW:min_value:approximate"
    ]