Pyarrow 为什么以及何时应该使用流缓冲区编写器?
Pyarrow why and when should I use a stream buffer writer?
我需要从自定义二进制文件(使用多处理和随机访问)中读取大量内容,以便执行计算并存储到 parquet 数据集。
我知道列数,但不知道要存储的项目数。
因此,文件被切割成N
个逻辑部分,每个部分由一个块reader函数处理。
所以进入这些功能我应该:
- 使用 python 类型
List
创建 x
列(通过追加进行动态分配)并在块的末尾创建一个记录批次 ?
- 与 (1) 相同,但每个
y
记录创建一个记录批次。这里我们按批控制物品的数量。这个过程可能会更慢,因为我们必须在每次迭代时放置一个条件 (if no_items == y:…
)
- 从 (1) 开始,最后记录批次存储到
RecordBatchStreamWriter
以便 return 缓冲区
- 从 (2) 开始,最后记录批次存储到
RecordBatchStreamWriter
以便 return 缓冲区
- 其他……
我都读了ipc, memory, arrow-streaming-columnar,但仍然不清楚如何处理巨大的随机访问文件。
感谢您的见解
如果您想要的输出是镶木地板数据集并且您的输入格式是自定义二进制文件,那么记录批处理 API 可能不会帮助您,除非您将计算分散到多个进程(而不是线程)。您提到了多处理,所以可能是这种情况,但我只是想确保您不是指多线程。
此外,当您说镶木地板数据集时,我不确定您是指一个巨大的镶木地板文件,还是指通用目录结构中的一些镶木地板文件。通常,“parquet 数据集”是多个 parquet 文件。
这项任务有很大的灵活性,因此您如何进行可能取决于您以后希望如何读取数据。
输出
多个文件。您创建多个 parquet 文件,其中每个 parquet 文件包含数据的所有列,但仅包含 X 行。如果您可以在数据中的某些列(例如测量日期/制造日期/设备 ID/实验标准)上对批次进行分区,那么您将能够非常有效地将它们用作以后的查询参数(例如,如果您稍后按测量日期查询,您可以简单地通过文件名和目录名找出要加载的文件)。在这种情况下,您将需要 dataset APIs。您也可以始终使用这种方法按行号进行分区,尽管您希望在这种情况下比单个文件的情况有更多的优势(使用仅支持整个文件镶木地板读取的第 3 方镶木地板工具仍然会更容易)。
单个文件。您可以创建一个巨大的单个镶木地板文件,该文件被分成许多“行组”。这将允许您稍后读取单个行组,或者通过一次处理单个行组来进行内存高效的批处理。这里的缺点是你只能按“行号”进行批处理,所以如果你以后想通过时间戳列之类的东西进行查找,那么你可能必须 read/scan 所有数据(除非你知道某种方式将时间戳映射到行号)。如果您想要这种方法,您将需要使用 ParquetWriter 来编写单独的行组。
输入
在写入上述任何内容之前,您需要以自定义格式读取并将数据转换为 Arrow 格式。如果您纯粹在 python 中这样做,这可能会很昂贵,但是,由于它是一种自定义格式,您不太可能能够使用内置的 Arrow 实用程序来读取数据。如果您的自定义格式有任何类型的本地库来读取数据,那么使用这些库读取数据、提取相关数据缓冲区并用箭头元数据包装它们以便箭头可以访问它们可能会更快。使用 python 操作生成的 Arrow 元数据对象(例如 tables / 分块数组等)应该很漂亮 trivial/fast.
如果您选择在 python 中解析文件,那么其成本可能会非常高,以至于您选择选项 1-4 并不重要。理想情况下,您希望能够将输入文件读入您打算写入的块中。希望从输入文件中读取固定大小的一批行(所有列)会很容易。
如果您希望您的输出格式按一列或多列进行分区(例如按测试标准进行分区),那么它会更加复杂。如果没有好的方法知道测试标准如何映射到行,您可能必须将整个文件作为单个 table 读入内存,进行多次传递,或者有很多文件(例如,而不是每个测试一个文件每个测试标准可以有 20 个标准,只需将输入文件读取为 20 个批次)。
IPC
既然你提到了多处理和记录批处理reader/writers,我将谈谈如何使用它们。如果您决定跨多个进程(甚至可能是多个服务器)读取您的文件,并且您希望这些进程进行通信,那么您可以使用记录批处理 reader/writers。例如,假设您有一个进程完全致力于读取自定义文件并将其解析为箭头格式。然后该进程可以使用记录批写入器将这些文件发送到您的下一个进程,该进程将使用记录批 reader 读取它们。例如,第二个进程然后可以完成将该记录批次写入一定数量的镶木地板文件的工作。记录批次reader/writer允许你写成箭头格式,以便进程间快速传输。
总结
如果不进一步了解您正在阅读的文件和您最终的 processing/querying 目标,就很难确切地说出该做什么。我认为对您的问题的简单回答是,您阅读输入的方式将取决于您最终希望如何创建输出。
我需要从自定义二进制文件(使用多处理和随机访问)中读取大量内容,以便执行计算并存储到 parquet 数据集。 我知道列数,但不知道要存储的项目数。
因此,文件被切割成N
个逻辑部分,每个部分由一个块reader函数处理。
所以进入这些功能我应该:
- 使用 python 类型
List
创建x
列(通过追加进行动态分配)并在块的末尾创建一个记录批次 ? - 与 (1) 相同,但每个
y
记录创建一个记录批次。这里我们按批控制物品的数量。这个过程可能会更慢,因为我们必须在每次迭代时放置一个条件 (if no_items == y:…
) - 从 (1) 开始,最后记录批次存储到
RecordBatchStreamWriter
以便 return 缓冲区 - 从 (2) 开始,最后记录批次存储到
RecordBatchStreamWriter
以便 return 缓冲区 - 其他……
我都读了ipc, memory, arrow-streaming-columnar,但仍然不清楚如何处理巨大的随机访问文件。
感谢您的见解
如果您想要的输出是镶木地板数据集并且您的输入格式是自定义二进制文件,那么记录批处理 API 可能不会帮助您,除非您将计算分散到多个进程(而不是线程)。您提到了多处理,所以可能是这种情况,但我只是想确保您不是指多线程。
此外,当您说镶木地板数据集时,我不确定您是指一个巨大的镶木地板文件,还是指通用目录结构中的一些镶木地板文件。通常,“parquet 数据集”是多个 parquet 文件。
这项任务有很大的灵活性,因此您如何进行可能取决于您以后希望如何读取数据。
输出
多个文件。您创建多个 parquet 文件,其中每个 parquet 文件包含数据的所有列,但仅包含 X 行。如果您可以在数据中的某些列(例如测量日期/制造日期/设备 ID/实验标准)上对批次进行分区,那么您将能够非常有效地将它们用作以后的查询参数(例如,如果您稍后按测量日期查询,您可以简单地通过文件名和目录名找出要加载的文件)。在这种情况下,您将需要 dataset APIs。您也可以始终使用这种方法按行号进行分区,尽管您希望在这种情况下比单个文件的情况有更多的优势(使用仅支持整个文件镶木地板读取的第 3 方镶木地板工具仍然会更容易)。
单个文件。您可以创建一个巨大的单个镶木地板文件,该文件被分成许多“行组”。这将允许您稍后读取单个行组,或者通过一次处理单个行组来进行内存高效的批处理。这里的缺点是你只能按“行号”进行批处理,所以如果你以后想通过时间戳列之类的东西进行查找,那么你可能必须 read/scan 所有数据(除非你知道某种方式将时间戳映射到行号)。如果您想要这种方法,您将需要使用 ParquetWriter 来编写单独的行组。
输入
在写入上述任何内容之前,您需要以自定义格式读取并将数据转换为 Arrow 格式。如果您纯粹在 python 中这样做,这可能会很昂贵,但是,由于它是一种自定义格式,您不太可能能够使用内置的 Arrow 实用程序来读取数据。如果您的自定义格式有任何类型的本地库来读取数据,那么使用这些库读取数据、提取相关数据缓冲区并用箭头元数据包装它们以便箭头可以访问它们可能会更快。使用 python 操作生成的 Arrow 元数据对象(例如 tables / 分块数组等)应该很漂亮 trivial/fast.
如果您选择在 python 中解析文件,那么其成本可能会非常高,以至于您选择选项 1-4 并不重要。理想情况下,您希望能够将输入文件读入您打算写入的块中。希望从输入文件中读取固定大小的一批行(所有列)会很容易。
如果您希望您的输出格式按一列或多列进行分区(例如按测试标准进行分区),那么它会更加复杂。如果没有好的方法知道测试标准如何映射到行,您可能必须将整个文件作为单个 table 读入内存,进行多次传递,或者有很多文件(例如,而不是每个测试一个文件每个测试标准可以有 20 个标准,只需将输入文件读取为 20 个批次)。
IPC
既然你提到了多处理和记录批处理reader/writers,我将谈谈如何使用它们。如果您决定跨多个进程(甚至可能是多个服务器)读取您的文件,并且您希望这些进程进行通信,那么您可以使用记录批处理 reader/writers。例如,假设您有一个进程完全致力于读取自定义文件并将其解析为箭头格式。然后该进程可以使用记录批写入器将这些文件发送到您的下一个进程,该进程将使用记录批 reader 读取它们。例如,第二个进程然后可以完成将该记录批次写入一定数量的镶木地板文件的工作。记录批次reader/writer允许你写成箭头格式,以便进程间快速传输。
总结
如果不进一步了解您正在阅读的文件和您最终的 processing/querying 目标,就很难确切地说出该做什么。我认为对您的问题的简单回答是,您阅读输入的方式将取决于您最终希望如何创建输出。