统计信息模式#

警告

此规范应视为实验性的。

原理#

统计信息对于快速查询处理非常有用。许多查询引擎使用统计信息来优化其查询计划。

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 的详细信息

名称

数据类型

可为空

备注

column(列)

int32

true(是)

从零开始的列索引,如果统计信息描述整个表或记录批次,则为 null。

列索引的计算规则与 RecordBatch 消息 相同。

statistics(统计信息)

map(映射)

false(否)

目标列、表或记录批次的统计信息。有关详细信息,请参阅下面的单独表格。

以下是 statisticsmap 的详细信息

键或项

数据类型

可为空

备注

key(键)

dictionary<values: utf8, indices: int32>

false(否)

字符串键是统计信息的名称。字典编码用于提高效率,因为相同的统计信息可能会针对不同的列重复。为精确和近似统计值分配不同的键。每个统计信息都有其自身的描述,如下所示。

items(项)

dense_union(密集联合)

false(否)

统计值是密集联合。它至少具有基于键中统计信息种类所需的所有类型。例如,当您具有 int64 不同计数统计信息和 float64 平均字节宽度统计信息时,您至少需要 int64float64 类型。请参阅下面每个统计信息的描述。

密集联合数组的每个字段都有名称,但我们没有为此标准化字段名称,因为我们可以通过类型代码而不是名称访问正确的字段。因此,我们可以对字段使用任何有效名称。

标准统计信息#

每个统计信息种类都有一个名称,该名称在每列或整个表的统计信息映射中显示为键。dictionary<values: utf8, indices: int32> 用于对名称进行编码以提高空间效率。

我们为同一统计信息的变体分配不同的名称,而不是使用标志。例如,我们为“不同计数”统计信息的精确值和近似值分配不同的统计信息名称。

冒号符号 : 将用作命名空间分隔符,如 自定义应用程序元数据。它可以在名称中多次使用。

ARROW 前缀是此规范当前和未来版本中预定义统计信息名称的保留命名空间。用户定义的统计信息不得使用它。例如,您可以使用您的产品名称作为命名空间,例如 MY_PRODUCT:my_statistics:exact

以下是预定义的统计信息名称

名称

数据类型

备注

ARROW:average_byte_width:exact(ARROW:平均字节宽度:精确)

float64

目标列中一行的平均大小(以字节为单位)。(精确)

ARROW:average_byte_width:approximate(ARROW:平均字节宽度:近似)

float64

目标列中一行的平均大小(以字节为单位)。(近似)

ARROW:distinct_count:exact(ARROW:不同计数:精确)

int64

目标列中不同值的个数。(精确)

ARROW:distinct_count:approximate(ARROW:不同计数:近似)

float64

目标列中不同值的个数。(近似)

ARROW:max_byte_width:exact (ARROW: 最大字节宽度: 精确)

int64

float64

目标列中一行的最大大小(以字节为单位)。(精确)

float64

ARROW:max_byte_width:approximate (ARROW: 最大字节宽度: 近似)

float64

目标列中一行的最大大小(以字节为单位)。(近似)

ARROW:max_value:exact(ARROW:最大值:精确)

取决于目标

目标列中一行的最大大小(以字节为单位)。(近似)

目标列中的最大值。(精确)

ARROW:max_value:approximate(ARROW:最大值:近似)

目标列中一行的最大大小(以字节为单位)。(近似)

目标列中的最大值。(近似)

ARROW:min_value:exact(ARROW:最小值:精确)

目标列中一行的最大大小(以字节为单位)。(近似)

取决于目标

目标列中的最小值。(精确)

int64

ARROW:min_value:approximate(ARROW:最小值:近似)

目标列中的最小值。(近似)

float64

ARROW:null_count:exact(ARROW:空值计数:精确)

int64

int64

目标列中空值的个数。(精确)

ARROW:null_count:approximate(ARROW:空值计数:近似)

float64

目标列中空值的个数。(近似)

ARROW:row_count:exact (ARROW: 行数: 精确)

int64

目标表、记录批次或数组中的行数。(精确)

ARROW:row_count:approximate (ARROW: 行数: 近似)

int64

目标表、记录批次或数组中的行数。(近似)

vendor_id: int32
passenger_count: int64

如果您发现某个统计信息可能对多个系统有用,请在 Apache Arrow 开发邮件列表 上提出建议。

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

当统计信息的生产者和消费者遵循先前商定的统计信息规范时,互操作性会得到改善。

示例#

名称

以下是一些帮助您理解的示例。

简单记录批次#

模式

5

数据

统计信息

0

数据

目标

2

数据

5

数据

记录批次

1

行数

统计信息

1

行数

目标

3

行数

2

行数

记录批次

0

vendor_id(供应商 ID)

空值个数

示例#

0

数据

1

行数

统计信息模式

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

如果您发现某个统计信息可能对多个系统有用,请在 Apache Arrow 开发邮件列表 上提出建议。

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

passenger_count(乘客人数)

统计信息

0

列索引

统计信息

0

列索引

目标

3

列索引

索引

5

列索引

统计信息数组

0

复杂记录批次#

统计信息

1

这使用嵌套类型。

99

这使用嵌套类型。

记录批次

20

col1(列 1)

统计信息

1

col1(列 1)

索引

3.0

col1(列 1)

统计信息数组

-3.0

col1.a(列 1.a)

统计信息

1

col1.a(列 1.a)

目标

2

vendor_id(供应商 ID)

空值个数

示例#

0

passenger_count(乘客人数)

1

列索引

2

复杂记录批次#

3

这使用嵌套类型。

4

col1(列 1)

5

col1.a(列 1.a)

近似最大值

统计信息模式

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

如果您发现某个统计信息可能对多个系统有用,请在 Apache Arrow 开发邮件列表 上提出建议。

[1, 1, 2, 0, null]

当统计信息的生产者和消费者遵循先前商定的统计信息规范时,互操作性会得到改善。

示例#

名称

以下是一些帮助您理解的示例。

col1.b(列 1.b)

模式

5

col1.b(列 1.b)

统计信息

1

col1.b(列 1.b)

目标

3

col1.b(列 1.b)

2

col1.b(列 1.b)

记录批次

0

vendor_id(供应商 ID)

空值个数

示例#

0

col1.b(列 1.b)

统计信息模式

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,
    ]

col1.b.item(列 1.b.项)

最小值

目标表、记录批次或数组中的行数。(近似)

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

如果您发现某个统计信息可能对多个系统有用,请在 Apache Arrow 开发邮件列表 上提出建议。

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

当统计信息的生产者和消费者遵循先前商定的统计信息规范时,互操作性会得到改善。

示例#

名称

以下是一些帮助您理解的示例。

col1.b(列 1.b)

模式

3

col1.b(列 1.b)

统计信息

0

col1.c(列 1.c)

统计信息

0

col1.c(列 1.c)

目标

3

col1.c(列 1.c)

索引

5

col1.c(列 1.c)

统计信息数组

0

col2(列 2)

统计信息

1

另请参阅 RecordBatch 消息 如何计算列索引。

99

另请参阅 RecordBatch 消息 如何计算列索引。

记录批次

20

简单数组#

统计信息

1

简单数组#

索引

3.0

简单数组#

统计信息数组

-3.0

vendor_id(供应商 ID)

空值个数

示例#

0

col1.b(列 1.b)

1

col1.c(列 1.c)

2

col2(列 2)

3

另请参阅 RecordBatch 消息 如何计算列索引。

4

简单数组#

近似最大值

统计信息模式

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"
    ]
数组