Skip to content

查询执行

我们在Reddit数据集上的示例查询是:

scan_csv

q1 = (
    pl.scan_csv("docs/assets/data/reddit.csv")
    .with_columns(pl.col("name").str.to_uppercase())
    .filter(pl.col("comment_karma") > 0)
)

如果我们在Reddit CSV上运行上述代码,查询将不会被评估。相反,Polars会将每一行代码添加到内部查询图中,并优化查询图。

当我们执行代码时,Polars 默认会执行优化后的查询图。

在整个数据集上执行

我们可以通过在查询上调用.collect方法来对整个数据集执行我们的查询。

scan_csv · collect

q4 = (
    pl.scan_csv(f"docs/assets/data/reddit.csv")
    .with_columns(pl.col("name").str.to_uppercase())
    .filter(pl.col("comment_karma") > 0)
    .collect()
)

shape: (14_029, 6)
┌─────────┬───────────────────────────┬─────────────┬────────────┬───────────────┬────────────┐
│ id      ┆ name                      ┆ created_utc ┆ updated_on ┆ comment_karma ┆ link_karma │
│ ---     ┆ ---                       ┆ ---         ┆ ---        ┆ ---           ┆ ---        │
│ i64     ┆ str                       ┆ i64         ┆ i64        ┆ i64           ┆ i64        │
╞═════════╪═══════════════════════════╪═════════════╪════════════╪═══════════════╪════════════╡
│ 6       ┆ TAOJIANLONG_JASONBROKEN   ┆ 1397113510  ┆ 1536527864 ┆ 4             ┆ 0          │
│ 17      ┆ SSAIG_JASONBROKEN         ┆ 1397113544  ┆ 1536527864 ┆ 1             ┆ 0          │
│ 19      ┆ FDBVFDSSDGFDS_JASONBROKEN ┆ 1397113552  ┆ 1536527864 ┆ 3             ┆ 0          │
│ 37      ┆ IHATEWHOWEARE_JASONBROKEN ┆ 1397113636  ┆ 1536527864 ┆ 61            ┆ 0          │
│ …       ┆ …                         ┆ …           ┆ …          ┆ …             ┆ …          │
│ 1229384 ┆ DSFOX                     ┆ 1163177415  ┆ 1536497412 ┆ 44411         ┆ 7917       │
│ 1229459 ┆ NEOCARTY                  ┆ 1163177859  ┆ 1536533090 ┆ 40            ┆ 0          │
│ 1229587 ┆ TEHSMA                    ┆ 1163178847  ┆ 1536497412 ┆ 14794         ┆ 5707       │
│ 1229621 ┆ JEREMYLOW                 ┆ 1163179075  ┆ 1536497412 ┆ 411           ┆ 1063       │
└─────────┴───────────────────────────┴─────────────┴────────────┴───────────────┴────────────┘

上面我们看到,在1000万行数据中,有14,029行符合我们的条件。

使用默认的collect方法,Polars会将所有数据作为一个批次处理。这意味着在查询的峰值内存使用点,所有数据都必须适合您的可用内存。

重用 LazyFrame 对象

请记住,LazyFrame是查询计划,即对计算的承诺,并不保证缓存常见的子计划。这意味着每次在定义后在单独的下游查询中重复使用它时,它都会重新计算。如果在不保持行顺序的LazyFrame上定义操作(例如group_by),那么每次运行时顺序也会改变。为了避免这种情况,请为此类操作使用maintain_order=True参数。

在大于内存的数据上执行

如果你的数据需要的内存超过了你可用的内存,Polars可能能够使用流式模式分批处理数据。要使用流式模式,你只需将streaming=True参数传递给collect

scan_csv · collect

q5 = (
    pl.scan_csv(f"docs/assets/data/reddit.csv")
    .with_columns(pl.col("name").str.to_uppercase())
    .filter(pl.col("comment_karma") > 0)
    .collect(streaming=True)
)

我们在这里更详细地查看流式处理

在部分数据集上的执行

当你在大型数据集上编写、优化或检查查询时,查询所有可用数据可能会导致开发过程变慢。

相反,您可以扫描分区的一个子集,或者在查询的开始和结束分别使用.head/.collect。请记住,对数据子集进行聚合和过滤的结果可能不能代表在完整数据上得到的结果。

scan_csv · collect · head

q9 = (
    pl.scan_csv(f"docs/assets/data/reddit.csv")
    .head(10)
    .with_columns(pl.col("name").str.to_uppercase())
    .filter(pl.col("comment_karma") > 0)
    .collect()
)

shape: (1, 6)
┌─────┬─────────────────────────┬─────────────┬────────────┬───────────────┬────────────┐
│ id  ┆ name                    ┆ created_utc ┆ updated_on ┆ comment_karma ┆ link_karma │
│ --- ┆ ---                     ┆ ---         ┆ ---        ┆ ---           ┆ ---        │
│ i64 ┆ str                     ┆ i64         ┆ i64        ┆ i64           ┆ i64        │
╞═════╪═════════════════════════╪═════════════╪════════════╪═══════════════╪════════════╡
│ 6   ┆ TAOJIANLONG_JASONBROKEN ┆ 1397113510  ┆ 1536527864 ┆ 4             ┆ 0          │
└─────┴─────────────────────────┴─────────────┴────────────┴───────────────┴────────────┘