Hub 文档

优化

Hugging Face's logo
加入 Hugging Face 社区

并获取增强的文档体验

开始使用

优化

我们简要地介绍了惰性求值和及早求值之间的区别。在此页面上,我们将展示如何使用惰性 API 来获得巨大的性能优势。

惰性求值 vs 及早求值

Polars 支持两种操作模式:惰性求值和及早求值。在及早求值 API 中,查询会立即执行,而在惰性求值 API 中,查询仅在“需要”时才会被评估。将执行推迟到最后一刻可以带来显着的性能优势,这也是在大多数非交互式情况下首选惰性 API 的原因。

示例

我们将使用上一页的示例来展示使用惰性 API 的性能优势。以下代码将计算来自 archive.org 的上传数量。

及早求值

import polars as pl
import datetime

df = pl.read_csv("hf://datasets/commoncrawl/statistics/tlds.csv", try_parse_dates=True)

df = df.select("suffix", "crawl", "date", "tld", "pages", "domains")
df = df.filter(
    (pl.col("date") >= datetime.date(2020, 1, 1)) |
    pl.col("crawl").str.contains("CC")
)
df = df.with_columns(
    (pl.col("pages") / pl.col("domains")).alias("pages_per_domain")
)
df = df.group_by("tld", "date").agg(
    pl.col("pages").sum(),
    pl.col("domains").sum(),
)
df = df.group_by("tld").agg(
    pl.col("date").unique().count().alias("number_of_scrapes"),
    pl.col("domains").mean().alias("avg_number_of_domains"),
    pl.col("pages").sort_by("date").pct_change().mean().alias("avg_page_growth_rate"),
).sort("avg_number_of_domains", descending=True).head(10)

惰性求值

import polars as pl
import datetime

lf = (
    pl.scan_csv("hf://datasets/commoncrawl/statistics/tlds.csv", try_parse_dates=True)
    .filter(
        (pl.col("date") >= datetime.date(2020, 1, 1)) |
        pl.col("crawl").str.contains("CC")
    ).with_columns(
        (pl.col("pages") / pl.col("domains")).alias("pages_per_domain")
    ).group_by("tld", "date").agg(
        pl.col("pages").sum(),
        pl.col("domains").sum(),
    ).group_by("tld").agg(
        pl.col("date").unique().count().alias("number_of_scrapes"),
        pl.col("domains").mean().alias("avg_number_of_domains"),
        pl.col("pages").sort_by("date").pct_change().mean().alias("avg_page_growth_rate"),
    ).sort("avg_number_of_domains", descending=True).head(10)
)
df = lf.collect()

耗时

在配备家用互联网连接的普通笔记本电脑上运行这两个查询会导致以下运行时间

  • 及早求值: 1.96
  • 惰性求值: 410 毫秒

惰性查询比及早查询快约 5 倍。 原因是查询优化器:如果我们延迟 collect 数据集直到最后,Polars 将能够推断出哪些列和行是必需的,并在读取数据时尽早应用过滤器。 对于诸如 Parquet 之类的包含元数据(例如,某一组行中的最小值、最大值)的文件格式,差异甚至可能更大,因为 Polars 可以根据过滤器和元数据跳过整个行组,而无需通过网络发送数据。

< > 在 GitHub 上更新