news 2026/9/9 20:06:31

Polars SQL 中的 CREATE TABLE:用 `SQLContext` 注册新表的三种方式与源码解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Polars SQL 中的 CREATE TABLE:用 `SQLContext` 注册新表的三种方式与源码解析

Polars SQL 中的 CREATE TABLE:用SQLContext注册新表的三种方式与源码解析

【免费下载链接】polarsExtremely fast Query Engine for DataFrames, written in Rust项目地址: https://gitcode.com/GitHub_Trending/po/polars

Polars 提供了SQLContext,让你用 SQL 语法直接对LazyFrameDataFrame执行查询。CREATE TABLE ... AS SELECT是其中最常用的语句之一——它基于一段 SELECT 查询在会话内创建并注册一张新表。本文以官方文档 docs/source/user-guide/sql/create.md 为主线,讲解CREATE TABLE的语法、运行结果与取值方式,并结合 Polars 源码与测试说明其背后三种建表路径的实现细节,帮助你在已有 SQL 代码库迁移或与 DataFrame 混合编程时正确使用这一特性。

一、基本语法与语义

SQLContext中,CREATE TABLE语句用于创建一张新表。其基础语法如下:

CREATE TABLE table_name AS SELECT ...

其中table_name是新表的名字,SELECT ...定义了将要存入该表的数据。Polars 的 SQL 方言参考了 PostgreSQL 的语法与函数行为,因此对熟悉 PostgreSQL 的读者来说这一点并不陌生。

这里必须澄清一个常见的误区:CREATE TABLE的“产物”并不是这张表本身,而是一个执行成功的提示。表会被登记进SQLContext的注册表中;如果想把它重新变回一个DataFrame,需要用一条SELECT * FROM ...语句去取回数据。这一点在文档的 Result 提示中着重强调,也是本文第三部分要展开的内容。

二、完整可运行的建表示例

下面的示例来自官方配套代码 docs/source/src/python/user-guide/sql/create.py,它是随文档一起被 mkdocs 渲染执行的真实代码:

import polars as pl data = {"name": ["Alice", "Bob", "Charlie", "David"], "age": [25, 30, 35, 40]} df = pl.LazyFrame(data) ctx = pl.SQLContext(my_table=df, eager=True) result = ctx.execute( """ CREATE TABLE older_people AS SELECT * FROM my_table WHERE age > 30 """ ) print(ctx.execute("SELECT * FROM older_people"))

运行流程拆解:

  1. 准备数据源:用pl.LazyFrame(data)构造一个懒加载的 DataFrame,列名为nameage
  2. 注册数据源:在初始化pl.SQLContext(my_table=df, eager=True)时,通过关键字参数把df注册为名为my_table的 SQL 表。这里eager=True表示执行查询后自动把结果收集为DataFrame
  3. 执行建表:调用ctx.execute(...)执行CREATE TABLE older_people AS SELECT * FROM my_table WHERE age > 30,从my_table中筛选出age大于 30 的所有行,生成新表older_people。筛选后该表仅剩 Charlie(35)与 David(40)两行。
  4. 取回数据:再次ctx.execute("SELECT * FROM older_people"),把已注册的older_people表作为查询结果输出。

你将会看到输出:

shape: (2, 2) ┌─────────┬─────┐ │ name ┆ age │ │ --- ┆ --- │ │ str ┆ i64 │ ╞═════════╪═════╡ │ Charlie ┆ 35 │ │ David ┆ 40 │ └─────────┴─────┘

三、CREATE TABLE的结果不是表,而是确认信息

由于CREATE TABLE属于数据定义语句(DDL),它的返回值并不携带数据。看 crates/polars-sql/src/context.rs 中的实现:

let df_created = df! { "Response" => [format!("CREATE TABLE {}", name.0.first().unwrap().as_ident().unwrap().value)] }; Ok(df_created.unwrap().lazy())

也就是说,execute()执行成功后返回的是一个只有单列Response、单行文本(例如"CREATE TABLE older_people")的微型帧,用于向调用方确认操作结果。真正建好的表被保存在SQLContext内部的注册表table_map中:

self.register(tbl_name, lf);

其底层即 SQLContext::register——把表名到LazyFrame的映射写入一张读写锁保护的 map。因此后续对这张表的访问,都需要经由SQLContext,通过SELECT * FROM ...JOIN等语句间接完成。

四、eager 与 lazy:什么时候能拿到DataFrame

SQL 查询在 Polars 中总是以惰性模式执行,以便利用完整的查询计划优化。上文ctx = pl.SQLContext(my_table=df, eager=True)中的eager参数就是用来控制收集行为的,两种方式二选一:

  • 在构造SQLContext时传入eager=True,让每次execute自动把LazyFrame结果收集成DataFrame
  • 保持上下文为 lazy,而在某一次查询调用时传eager=True或显式.collect()

Python 侧 py-polars/src/polars/sql/context.py 中execute()的结尾正是这条规则:

return res.collect() if eager or self._eager_execution else res

在第一个示例里,两次execute都返回DataFrame:第一次返回的是Response确认表,第二次返回的是older_people的实际数据。

提示:如果CREATE TABLE的子查询基于 CSV、NDJSON 等文件做懒加载,建表本身只是定义逻辑,真正扫描文件数据会被推迟到SELECT * FROM older_people收集时,从而可以只加载必要的行与列。

五、三种建表路径:AS query、列定义与LIKE

虽然 create.md 重点示范了AS SELECT的形式,但从源码看 Polars 的CREATE TABLE支持三种互斥的建表路径。测试 py-polars/tests/unit/sql/test_table_operations.py 一次覆盖了全部三种用法:

with pl.SQLContext() as ctx: # test all three ways of creating a new table ctx.execute("CREATE TABLE tbl1(colx VARCHAR, coly DATE, colz ARRAY<DOUBLE>)") ctx.execute("CREATE TABLE tbl2 AS SELECT * FROM tbl1") ctx.execute("CREATE TABLE tbl3 LIKE tbl2") df = ctx.execute("SELECT * FROM tbl3", eager=True)

对应到 execute_create_table 的实现,会按(query, columns, like)组合进行分支:

  1. CREATE TABLE [IF NOT EXISTS] <name> AS <query>:子查询存在且未提供列定义时,直接递归执行子查询得到LazyFrame——这是 create.md 展示的路径,其子查询可以是任意合法的 SELECT、UNION、JOIN,甚至引用其他已注册表或READ_CSV之类的表函数。
  2. CREATE TABLE [IF NOT EXISTS] <name> (<coldef>, ...):仅给出列定义时,把每个 SQL 数据类型通过map_sql_dtype_to_polars映射为 Polars 数据类型(如VARCHAR → StringDATE → DateARRAY<DOUBLE> → List(Float64)),构建一个只含 schema、不含数据的空表。
  3. CREATE TABLE [IF NOT EXISTS] <name> LIKE <table>:复制一张已存在表的 schema 但清空数据;若源表不存在会直接报错table given in LIKE does not exist

如果三个来源一个都没给出,会抛出错误CREATE TABLE expected a query, column definitions, or LIKE clause;如果同时给出多个来源(比如既有AS子查询又带列定义),会报告“互斥选项”错误。此外,虽然内部结构支持if_not_exists,但从代码注释看 Polars 的CREATE本身已具备幂等友好处理,而CREATE OR REPLACE TABLECREATE TEMPORARY TABLE及大批存储/分区/物化子句均不被支持,详见 validate_create_table。

六、支持范围与限制速览

一句话概括文档 docs/source/user-guide/sql/intro.md 的结论:Polars 不实现完整 SQL 规范,但覆盖了最常用语句的一个子集,并尽可能贴近 PostgreSQL 语义。

已支持的CREATE相关语句包括:

  • CREATE TABLE xxx AS ...(本文主题);
  • 列出注册表的SHOW TABLES
  • 删除表的DROP TABLE [IF EXISTS] tablename
  • 清空表的TRUNCATE TABLE [IF EXISTS] tablename

当前尚未支持的包括INSERT/UPDATE/DELETE语句,以及ANALYZE之类的元查询——这意味着在 Polars 中建表不等于持久化存储,也不支持对表做行级写操作。

七、更进一步

  • CREATE TABLE建出的新表与子查询共享 schema 推断:name会被推断为StringageInt64(参见上文输出中stri64的标注)。
  • 想让新表与文件读取无缝衔接,可把READ_CSVREAD_NDJSON等表函数放进AS子查询,测试 test_create_table_from_file_io 演示了CREATE TABLE foods AS SELECT * FROM READ_CSV(...)的用法;类似机制同样适用于scan_pyarrow_dataset指向的 S3、Azure Data Lake 等云数据源。
  • 由于表实际存储的是LazyFrame引用,会话内可继续用register/unregister/register_globals/register_many等 API 增删表(Python 侧定义见 py-polars/src/polars/sql/context.py),从而灵活组合 DataFrame 编程与 SQL 编程两种范式。

结合本文的核心结论——CREATE TABLE负责把一段查询逻辑注册为新表并返回确认信息,而真正的数据要依靠后续SELECT才能取回——你就能在迁移 SQL 工作负载到 Polars 时,把建表语句当作“物化中间视图”来使用,同时继续享受 Polars 原生引擎带来的惰性优化与执行性能。

【免费下载链接】polarsExtremely fast Query Engine for DataFrames, written in Rust项目地址: https://gitcode.com/GitHub_Trending/po/polars

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 20:05:40

动态规划入门:从斐波那契到背包问题的状态转移全解析

动态规划这四个字&#xff0c;大概是算法学习路上劝退率最高的名词之一。我一开始接触动态规划时&#xff0c;完全被"状态""转移方程""最优子结构"这些术语砸晕&#xff0c;一度怀疑是自己数学基础太差。后来刷了足够多题目、反复推演过几个经典…

作者头像 李华
网站建设 2026/9/9 20:05:36

Open Model Zoo:预训练模型下载、转换与部署实战指南

简介&#xff1a;Open Model Zoo是一套面向深度学习推理开发者的预训练模型库与演示集合&#xff0c;核心价值在于让开发者无需从零训练模型&#xff0c;即可获得经过优化的高质量模型&#xff0c;并借助配套演示快速构建或验证自身的人工智能应用。这份资源整理了大量可复用的…

作者头像 李华
网站建设 2026/9/9 20:05:33

答辩PPT神器实测:5款AI生成工具横评与选型指南

又到毕业季&#xff0c;后台收到好几个人问同一件事&#xff1a;答辩PPT有没有什么工具能一键生成&#xff0c;不用自己一页页排版&#xff1f;问的人多了&#xff0c;我干脆把手头用过的所有主流生成式PPT工具重新拉出来测了一遍。这篇文章就是那轮实测的完整记录&#xff0c;…

作者头像 李华
网站建设 2026/9/9 20:02:09

iptables 实战指南:从表链原理到端口转发与故障排查

做运维这些年&#xff0c;iptables 是我绕不开的一个老朋友。平时排查问题、做访问控制、配端口转发&#xff0c;随手敲几行命令就能解决大半需求。但说实话&#xff0c;很多人对它的认知一直停留在“会复制粘贴几条规则”的层面&#xff0c;一旦遇到诡异的网络问题就抓瞎。这篇…

作者头像 李华
网站建设 2026/9/9 20:01:55

Grafana接入Zabbix实现监控可视化:插件安装、数据源配置与仪表盘实战

你有没有遇到过这种场景&#xff1a;Zabbix 里监控项堆了一大堆&#xff0c;主机列表密密麻麻&#xff0c;可每次想给老板展示一下业务系统的健康度&#xff0c;或者排查一次跨多台主机的性能问题&#xff0c;都得在原生的图形界面里反复切换、翻页、等加载。我当初搞了大概两周…

作者头像 李华