Dask 数据帧 known_divisions 和性能
Dask dataframes known_divisions and performance
我有几个文件,其中有一个名为 idx
的列,我想将其用作索引。获得的数据框有大约 13M 行。我知道我可以用这种方式读取和分配索引(这很慢 ~40 秒)
df = dd.read_parquet("file-*.parq")
df = df.set_index("idx")
或以这种其他方式(快约 40 毫秒)
df = dd.read_parquet("file-*.parq", index = "idx")
计算长度的简单操作使用第二种方法快约 4 倍。我不明白的是
- 第一种情况
df.known_divisions
returns True
而第二种情况 False
。我期望相反的行为。然后我在 df
之上做了几个操作,没有 known_division 我总是获得更好的性能。我绞尽脑汁想弄清楚这是否是故意发生的。
- 分区数就是文件数。如何设置不同的分区数?
更新
这不仅仅是计算 len
哪个更快。在我的计算中,我使用 groupby 创建了 4 个新数据帧,应用并加入了几次,这些是时间
| |Load and reindex (s)|Load with index (s)|
|:-----------------|-------------------:|------------------:|
| load | 12.5000 | 0.0124 |
| grp, apply, join | 11.4000 | 6.2700 |
| compute() | 146.0000 | 125.0000 |
| TOTAL | 169.9000 | 131.2820 |
当您使用第一种方法时,dask 正在加载数据,并在执行您要求的任何计算之前根据您选择的列的值对行进行分区(这涉及打乱所有磁盘上的块)为了。在计算长度的情况下,这都是浪费时间,因为了解索引划分对此毫无帮助,但涉及该索引的进一步计算(例如,连接操作)会快得多。
在第二个版本中,您断言您选择的列是索引,但 dask 不会在您没有明确要求的情况下打乱数据。如果它碰巧在 parquet 元数据中保存了统计信息,并且每个 parquet 块的 max/min 是这样的,那么它们形成一个单调序列(即,第二个块中 'idx' 的所有值都是大于第一个中的所有值,等等),那么您将像以前一样知道涉及索引的某些操作的除法和优化性能。如果不满足这些条件,则设置了索引列,但分区未知 - 同样,这对于计算长度完全没问题。
我有几个文件,其中有一个名为 idx
的列,我想将其用作索引。获得的数据框有大约 13M 行。我知道我可以用这种方式读取和分配索引(这很慢 ~40 秒)
df = dd.read_parquet("file-*.parq")
df = df.set_index("idx")
或以这种其他方式(快约 40 毫秒)
df = dd.read_parquet("file-*.parq", index = "idx")
计算长度的简单操作使用第二种方法快约 4 倍。我不明白的是
- 第一种情况
df.known_divisions
returnsTrue
而第二种情况False
。我期望相反的行为。然后我在df
之上做了几个操作,没有 known_division 我总是获得更好的性能。我绞尽脑汁想弄清楚这是否是故意发生的。 - 分区数就是文件数。如何设置不同的分区数?
更新
这不仅仅是计算 len
哪个更快。在我的计算中,我使用 groupby 创建了 4 个新数据帧,应用并加入了几次,这些是时间
| |Load and reindex (s)|Load with index (s)|
|:-----------------|-------------------:|------------------:|
| load | 12.5000 | 0.0124 |
| grp, apply, join | 11.4000 | 6.2700 |
| compute() | 146.0000 | 125.0000 |
| TOTAL | 169.9000 | 131.2820 |
当您使用第一种方法时,dask 正在加载数据,并在执行您要求的任何计算之前根据您选择的列的值对行进行分区(这涉及打乱所有磁盘上的块)为了。在计算长度的情况下,这都是浪费时间,因为了解索引划分对此毫无帮助,但涉及该索引的进一步计算(例如,连接操作)会快得多。
在第二个版本中,您断言您选择的列是索引,但 dask 不会在您没有明确要求的情况下打乱数据。如果它碰巧在 parquet 元数据中保存了统计信息,并且每个 parquet 块的 max/min 是这样的,那么它们形成一个单调序列(即,第二个块中 'idx' 的所有值都是大于第一个中的所有值,等等),那么您将像以前一样知道涉及索引的某些操作的除法和优化性能。如果不满足这些条件,则设置了索引列,但分区未知 - 同样,这对于计算长度完全没问题。