Skip to main content

描述

pg_clickhouse 是一个 PostgreSQL 扩展,可在 ClickHouse 数据库上远程执行查询, 其中包括一个[外部数据包装器]。它支持 PostgreSQL 13 及以上版本,以及 ClickHouse 23.3 及以上版本。

快速开始

试用 pg_clickhouse 最简单的方式是使用 [Docker 镜像],其中包含 标准的 PostgreSQL Docker 镜像,并集成了 pg_clickhouse 和 [re2][re2 扩展] 扩展:
请参阅教程,开始了解如何导入 ClickHouse 表并下推查询。

用法

版本策略

pg_clickhouse 的公开发布版本遵循[语义化版本控制]。
  • API 发生变更时,递增主版本号
  • SQL 发生向后兼容的变更时,递增次版本号
  • 仅有 binary 变更时,递增补丁版本号
安装后,PostgreSQL 会跟踪两种版本形式:
  • 库版本 (在 PostgreSQL 18 及以上版本中由 PG_MODULE_MAGIC 定义) 包含完整的语义化版本号,可在 pgch_version() 函数的输出或 Postgres pg_get_loaded_modules() 函数中查看。
  • 扩展版本 (在控制文件中定义) 仅包含主版本号和次版本号,可在 pg_catalog.pg_extension 表、pg_available_extension_versions() 函数的输出以及 \dx pg_clickhouse 中查看。
在实际使用中,这意味着补丁版本号递增的发布 (例如从 v0.1.0 升级到 v0.1.1) 会让所有已加载 v0.1 的数据库直接受益,无需运行 ALTER EXTENSION 即可获得升级内容。 相反,次版本号或主版本号递增的发布会附带 SQL 升级脚本,所有包含该扩展的现有数据库都必须运行 ALTER EXTENSION pg_clickhouse UPDATE 才能获得升级内容。

DDL SQL 参考

以下 SQL DDL 表达式使用 pg_clickhouse。

CREATE EXTENSION

使用 CREATE EXTENSION 将 pg_clickhouse 扩展添加到数据库中:
使用 WITH SCHEMA 将其安装到指定的 schema 中 (推荐) :

ALTER EXTENSION

使用 ALTER EXTENSION 修改 pg_clickhouse。示例:
  • 安装 pg_clickhouse 的新 release 后,使用 UPDATE 子句:
  • 使用 SET SCHEMA 将该扩展移动到新的 schema:

DROP EXTENSION

使用 DROP EXTENSION 从数据库中删除 pg_clickhouse:
如果存在任何依赖于 pg_clickhouse 的对象,此命令会失败。请使用 CASCADE 子句将它们一并删除:

CREATE SERVER

使用 CREATE SERVER 创建连接到 ClickHouse 服务器的外部服务器。示例:
支持的选项有:
  • driver:要使用的 ClickHouse 连接驱动程序,可以是 “binary” 或 “http”。必填。
  • compression:binary driver 的 native 协议压缩,可选值为 “none”、“lz4” 或 “zstd”。默认为 “lz4”。http 驱动会忽略此选项。
  • dbname:连接时使用的 ClickHouse 数据库。默认为 “default”。
  • host:ClickHouse server 的主机名。默认为 “localhost”;
  • port:连接到 ClickHouse server 时使用的端口。默认值 如下:
    • 如果 driver 为 “binary” 且 host 是 ClickHouse Cloud 主机,则为 9440
    • 如果 driver 为 “binary” 且 host 不是 ClickHouse Cloud 主机,则为 9004
    • 如果 driver 为 “http” 且 host 是 ClickHouse Cloud 主机,则为 8443
    • 如果 driver 为 “http” 且 host 不是 ClickHouse Cloud 主机,则为 8123
  • min_tls_version:对使用 TLS 的连接协商的最低 TLS 协议版本。 可选值为 TLSv1TLSv1.1TLSv1.2TLSv1.3。默认值 为 TLS 库自身的最低版本。适用于两种驱动程序。
  • secure:控制连接是否使用 TLS。可选值为:
    • auto (默认) :当 host 是 ClickHouse Cloud 主机或 port 是安全端口时使用 TLS;否则使用 plaintext。
    • on (或 true/yes/1) :始终使用 TLS。默认 port 为 8443 (“http”) 或 9440 (“binary”) 。
    • off (或 false/no/0) :从不使用 TLS。默认 port 为 8123 (“http”) 或 9000 (“binary”) 。

ALTER SERVER

使用 ALTER SERVER 修改 外部服务器。示例:
这些选项与 CREATE SERVER 中的选项相同。

DROP SERVER

使用 DROP SERVER 删除 外部服务器:
如果有任何其他对象依赖于该服务器,此命令将失败。使用 CASCADE 还会 一并删除这些依赖对象:

CREATE USER MAPPING

使用 CREATE USER MAPPING 将 PostgreSQL 用户映射为 ClickHouse 用户。例如,使用 taxi_srv 外部服务器 连接时,可将当前 PostgreSQL 用户映射为远程 ClickHouse 用户:
支持的选项如下:
  • user:ClickHouse 用户名。默认为 “default”。
  • password:ClickHouse 用户的密码。

ALTER USER MAPPING

使用 ALTER USER MAPPING 修改用户映射的定义:
这些选项与 CREATE USER MAPPING 中的选项相同。

DROP USER MAPPING

使用 DROP USER MAPPING 移除用户映射:

IMPORT FOREIGN SCHEMA

使用 IMPORT FOREIGN SCHEMA 可将 ClickHouse 数据库中定义的所有表作为外部表导入到 PostgreSQL schema 中:
使用 LIMIT TO 将导入限制到特定表:
使用 EXCEPT 排除这些表:
pg_clickhouse 将获取指定 ClickHouse 数据库 (上述示例中的 “demo”) 中所有表的列表,获取每个表的列定义, 并执行 CREATE FOREIGN TABLE 命令来创建 外部表。列将使用支持的数据 类型进行定义,并在可检测的情况下使用 CREATE FOREIGN TABLE 支持的选项。
导入标识符的大小写保留IMPORT FOREIGN SCHEMA 会对导入的表名和列名运行 quote_identifier(), 为包含大写字母或空格的标识符加上双引号。 因此,这类表名和列名在 PostgreSQL 查询中必须用双引号括起来。 如果名称全部为小写且不包含空格字符,则无需加引号。例如,给定以下 ClickHouse 表:
IMPORT FOREIGN SCHEMA 会创建这个外部表:
因此,查询中也必须正确加引号,例如:
若要创建名称不同或全部为小写 (因此 不区分大小写) 的对象,请使用 CREATE FOREIGN TABLE

CREATE FOREIGN TABLE

使用 CREATE FOREIGN TABLE 创建可查询 ClickHouse 数据库中数据的外部表:
支持的表选项如下:
  • database:远程 数据库 的名称。默认使用为 外部服务器 定义的 数据库。
  • table_name:远程表的名称。默认使用为 foreign table 指定的名称。
  • engine:ClickHouse 表使用的[表引擎]。对于 CollapsingMergeTree()AggregatingMergeTree(),pg_clickhouse 会自动将参数应用于在该表上执行的函数表达式。
对于每一列,请使用与远程 ClickHouse 数据 类型相对应的数据类型。支持的列选项如下:
  • column_name:ClickHouse 端的列名,在反解析查询和 插入语句时,会优先使用该名称而不是 PostgreSQL attribute 名称。 这对于将未加引号的小写 PostgreSQL 列名映射到 区分大小写的 ClickHouse 列很有用,例如:
  • AggregateFunction:应用于 AggregateFunction Type 列的聚合函数名称。将数据类型映射为传递给该函数的 ClickHouse 类型,并通过相应的列选项指定 聚合函数名称,pg_clickhouse 会自动在计算该列的聚合函数后追加 Merge
  • SimpleAggregateFunction:应用于 SimpleAggregateFunction Type 列的聚合函数名称。将数据类型映射为 传递给该函数的 ClickHouse 类型,并通过相应的 列选项指定聚合函数名称。

ALTER FOREIGN TABLE

使用 ALTER FOREIGN TABLE 修改外部表的定义:
支持的表和列选项与 CREATE FOREIGN TABLE 中的相同。

DROP FOREIGN TABLE

使用 DROP FOREIGN TABLE 删除外部表:
如果有任何对象依赖于该外部表,此命令将失败。 使用 CASCADE 子句也会将它们一并删除:

DML SQL 参考

下面的 SQL DML 表达式可能会用到 pg_clickhouse。示例基于 以下 ClickHouse 表:

EXPLAIN

EXPLAIN 命令可按预期运行,但 VERBOSE 选项会触发输出 ClickHouse 的 “Remote SQL” 查询:
此查询会通过 “Foreign Scan” 计划节点下推到 ClickHouse,作为远程 SQL 执行。

SELECT

使用 SELECT 语句在 pg_clickhouse 表上执行查询,与在任何其他表上执行查询无异:
pg_clickhouse 会尽可能将查询执行下推到 ClickHouse,包括聚合函数。使用 EXPLAIN 可确定 下推的范围。例如,对于上述查询,所有执行都会下推到 ClickHouse
pg_clickhouse 还会将同一远程服务器上的表之间的 JOIN 下推:
如果不经过仔细调优,与本地表连接会生成效率较低的查询。在这个示例中,我们创建了 nodes 表的一个本地副本,并与它连接,而不是连接远程表:
在这种情况下,我们可以通过 按 node_id 而不是本地列分组,将更多聚合下推到 ClickHouse,然后再 与查找表进行 join:
“Foreign Scan”节点现在会按 node_id 下推聚合,将需要从 Postgres 拉回的行数从 1000 行 (全部行) 减少到仅 8 行,即每个节点 1 行。

分区表

PostgreSQL [分区表]可以同时包含本地分区和由 ClickHouse 支持的外部分区。常见的布局是将较早的数据迁移到 ClickHouse,而较新的数据保留在 PostgreSQL 中:
有关如何将数据从本地分区迁移到外部分区的示例,请参阅 offload-partition.sql 跨本地分区和外部分区的聚合需要启用 partitionwise aggregation,而 PostgreSQL 默认将其禁用:
启用 enable_partitionwise_aggregate 后,PostgreSQL 会在 Append 下方计算部分聚合,再由上方的最终聚合将这些部分结果合并为最终结果。pg_clickhouse 会将外部分区的部分聚合下推至 ClickHouse:

部分聚合何时可以下推

PostgreSQL 将部分聚合表示为转换状态,并由最终化步骤在各分区间合并。只有当 pg_clickhouse 能将分区的部分聚合表示为 ClickHouse 值时,才能将其下推:
  • 可分解聚合函数的转换状态本身就是最终值,因此可以直接下推:countsumminmaxbool_and/everybool_orbit_andbit_orbit_xor
  • 作用于整数的 avg 会将其 {count, sum} 状态作为数组下推。
  • 作用于浮点数的 avgvar_popvar_sampstddev_popstddev_samp 会将其 {N, sum, squared deviations 的总和} 状态作为数组下推。
FILTER (WHERE …) 也可以与这些聚合函数一起下推。

何时回退

转换状态为 PostgreSQL 不透明 internal 类型的聚合没有可移植的表示形式,因此外部分区会转而拉取其行,并在本地进行聚合。这包括所有基于 numeric 的聚合,以及 avg(bigint)avg(interval)DISTINCT、有序集聚合和可变参数聚合也会回退。

PREPARE, EXECUTE, DEALLOCATE

自 v0.1.2 起,pg_clickhouse 支持参数化查询,主要通过 PREPARE 命令创建:
像平常一样使用 EXECUTE 执行预处理语句:
参数化执行会导致 http 驱动 在 25.8 之前的 ClickHouse 版本中 无法正确转换 DateTime 时区,因为该[底层缺陷]当时尚未[修复]。请注意,PostgreSQL 有时即使不使用 PREPARE,也会采用参数化查询计划。对于任何需要精确时区转换的查询, 如果无法升级到 25.8 或更高版本,请改用 binary driver
与往常一样,pg_clickhouse 会下推聚合操作,如 EXPLAIN 的详细输出所示:
请注意,它发送的是完整的日期值,而不是参数占位符。 前五次请求都是如此,如 PostgreSQL [PREPARE 说明] 中所述。到第六次执行时,它会发送 ClickHouse {param:type} 风格的[查询参数]: 参数:
使用 DEALLOCATE 解除分配预处理语句:

INSERT

使用 INSERT 命令向远程 ClickHouse 表中插入值:

COPY

使用 COPY 命令将一个批次的数据行插入远程 ClickHouse 表:
⚠️ 批次 API 的限制 pg_clickhouse 尚未支持 PostgreSQL FDW 的批次 insert API。因此,COPY 目前通过 INSERT 语句 插入记录。后续版本将对此进行改进。

LOAD

使用 LOAD 加载 pg_clickhouse 共享库:
通常不需要使用 LOAD,因为 Postgres 会在首次使用 pg_clickhouse 的任一功能 (函数、外部表等) 时自动加载它。 LOAD pg_clickhouse 可能有用的一种情况是:在执行依赖这些参数的查询之前,先通过 SET 设置 pg_clickhouse 参数。

SET

使用 SET 来设置 pg_clickhouse 的自定义配置参数。

pg_clickhouse.session_settings

pg_clickhouse.session_settings 参数用于配置在后续查询中要设置的 [ClickHouse 设置]。示例:
默认值为
将其设为空字符串即可恢复为 ClickHouse server 的设置 — 但请注意,下推的正确性取决于其中某些默认值: OUTER JOIN 的 join_use_nulls 以及 IN 家族的 transform_null_in (请参阅 IN 和 NULL 语义) 。
其语法为由逗号分隔的键/值对列表,各项之间以一个或 多个空格分隔。键必须与 [ClickHouse 设置] 对应。在值中,空格、 逗号和反斜杠都要用反斜杠转义:
或者使用单引号包裹值,以避免转义空格和逗号;也可以考虑 使用[美元引号表示法],这样就无需再使用双引号:
如果你更注重可读性,并且需要设置很多项,可以分成多 行,例如:
当这些设置会干扰 pg_clickhouse 自身运行时,其中一些设置将被忽略。包括:
  • date_time_output_format:http 驱动要求其为 “iso”
  • format_tsv_null_representation:http 驱动要求使用默认值
  • output_format_tsv_crlf_end_of_line:http 驱动要求使用默认值
除此之外,pg_clickhouse 不会校验这些设置,而是会在每次查询时将它们传递给 ClickHouse。因此,它支持各个 ClickHouse 版本中的所有设置。 请注意,必须先加载 pg_clickhouse,才能设置 pg_clickhouse.session_settings;可以使用共享库预加载,或者 直接使用该扩展中的某个对象以确保其被加载。

pg_clickhouse.pushdown_regex

pg_clickhouse.pushdown_regex 参数用于控制 pg_clickhouse 是否对正则表达式函数和操作符执行下推。默认情况下会执行下推; 将此参数设置为 false 可阻止下推:
详见正则表达式

ALTER ROLE

使用 ALTER ROLESET 命令,可为特定角色预加载 pg_clickhouse, 和/或 SET 其参数:
使用 ALTER ROLE’s RESET 命令重置 pg_clickhouse 的预加载 和/或相关参数:

预加载

如果每个或几乎每个 Postgres 连接都需要使用 pg_clickhouse, 请考虑使用共享库预加载来自动加载它:

session_preload_libraries

在每次建立与 PostgreSQL 的新连接时加载共享库:
有助于在不重启服务器的情况下应用更新:只需 重新连接即可。也可以通过 ALTER ROLE 为特定用户或角色设置。

shared_preload_libraries

在启动时将共享库加载到 PostgreSQL 主进程中:
有助于减少每个会话的内存占用和加载开销,但在库更新时需要 重启集群。

数据类型

pg_clickhouse 将以下 ClickHouse 数据类型映射为 PostgreSQL 数据 类型。IMPORT FOREIGN SCHEMA 在导入列时会使用 PostgreSQL 列中的第一种类型;其他类型可在 CREATE FOREIGN TABLE 语句中使用: 任何列也可读取为 textvarchar 或其他 String 类型。该值 会采用上述 PostgreSQL 类型,然后通过该类型的输出 函数进行呈现。超过 bigint 最大值的 UInt64 值仍会报错,因此请使用 ClickHouse toString() 函数呈现这些值。 更多说明和细节如下。

BYTEA

ClickHouse 不提供与 PostgreSQL BYTEA 类型等效的类型,但允许将任意字节存储在 String 类型中。一般情况下,ClickHouse 字符串应映射到 PostgreSQL 的 TEXT 类型;若需使用二进制数据,则应映射到 BYTEA。示例:
最终的 SELECT 查询将输出:
请注意,如果 ClickHouse 列中存在空字节,使用 TEXT 列的外部表将无法输出正确的值:
输出结果:
请注意,第二行和第三行包含被截断的值。这是因为 PostgreSQL 依赖以 nul 结尾的字符串,且不支持在字符串中 包含 nul 字符。 尝试向 TEXT 列插入二进制值将会成功,并按预期运行:
文本列将是正确的:
但如果按 BYTEA 读取,则不会:
一般来说,TEXT 列只用于编码字符串,BYTEA 列只用于二进制数据, 并且绝不要在两者之间切换。

函数与 operator 参考

函数

这些函数提供了查询 ClickHouse 数据库的接口。

clickhouse_raw_query

已弃用:clickhouse_raw_query() 会发出弃用 Warning,并将在下一个 release 中 移除。请使用 clickhouse_query 读取行,并使用 clickhouse_perform 执行 不返回任何内容的语句。两者都会复用已配置 server 的 driver、credentials、 database 和 连接缓存,而非使用临时 connection string。
连接到 ClickHouse 服务,执行单个 查询,然后断开连接。可选的第二个参数用于指定连接 字符串,默认为 host=localhost port=8123。支持的连接 参数如下:
  • driver:要使用的连接驱动程序,可以是 “http” 或 “binary”;默认为 “http”
  • host:要连接到的主机;必填。
  • port:要连接的端口。对于 “http” 驱动程序,默认为 8123;对于 “binary” 驱动程序,默认为 9000。当 host 是 ClickHouse Cloud 主机时, 则分别切换为 84439440
  • dbname:要连接到的数据库名称。
  • username:连接时使用的用户名;默认为 default
  • password:用于身份验证的密码;默认无密码
两种驱动程序都返回制表符分隔的行 (NULL 值为 \N) ,但各值的 表示形式不同:“http” 驱动程序会原样返回 ClickHouse 自有的 TSV 格式,而 “binary” 驱动程序会将每个值传递给其 PostgreSQL 输出函数。 默认情况下,没有任何角色具有对此函数的 EXECUTE 权限;请考虑仅向 确实需要执行临时 ClickHouse 查询的角色 GRANT 此权限, 例如专用的 ClickHouse 管理员角色: 适用于不返回记录的查询,但如果查询确实返回值, 则会作为单个文本值返回:

clickhouse_server_version

报告指定 外部服务器 的 ClickHouse 服务器版本,格式为 major.minor.patch。如有必要,将使用该服务器的选项和当前用户的 user mapping 进行连接:
从原生协议连接的握手过程中读取版本信息,或通过 HTTP 执行单个 SELECT version() 查询获取版本信息,并在连接的整个生命周期内缓存该信息。

clickhouse_query

针对已配置的外部服务器执行查询,并将返回的 行作为关系返回,同时将每个 ClickHouse 结果列映射为列定义列表中 指定的 PostgreSQL 类型。它会复用该服务器的 driver、 凭据、数据库和连接缓存。 第一个参数是通过 CREATE SERVER 创建的服务器名称。必须提供 列定义列表 (AS name(col type, ...)) :PostgreSQL 在拉取行之前需要知道 结果形态,且该列表必须与查询返回的列相匹配。值会以与外部表列相同的方式 从 ClickHouse 转换为声明的类型。不返回结果的语句 (如 DDL) 无需声明任何内容;请改用 clickhouse_perform 执行它们。 默认情况下,任何角色都没有 EXECUTE 权限;请向角色 GRANT 权限,以允许其使用 该函数。

clickhouse_perform

对已配置的 外部服务器 执行一条语句,并丢弃 所有结果。适用于不返回行的语句,例如 DDL;此时 clickhouse_query 没有可声明的结果形态。它以与 clickhouse_query 相同的方式 解析 server,并复用其 driver、credentials、database 和 连接缓存。 作为存储过程,必须通过 CALL 而非 SELECT 调用,并且不返回 行。默认情况下,没有任何角色拥有 EXECUTE 权限;向角色授予 GRANT 权限即可允许其 使用该存储过程。

下推函数

pg_clickhouse 会将条件子句 (HAVINGWHERE 子句) 中使用的部分 PostgreSQL 内置函数下推到 ClickHouse 中执行。该子集与 ClickHouse 中的对应函数如下:

下推操作符

IN 和 NULL 语义

ClickHouse 对 IN 采用二值逻辑:当探测值未找到 匹配项时,即使涉及 NULL,也会返回 0,而 PostgreSQL 则会计算为 NULL。为保留 PostgreSQL 语义,pg_clickhouse 会无条件下推针对常量列表或数组的 IN 系列操作 (INNOT IN= ANY= ALL<> ANY<> ALL) :若能够证明探测值和数组元素均不可能为 NULL,则使用原生或开销较低的形式; 否则使用带保护条件的 CASE 形式,在运行时检查 NULL 值, 从而在所有上下文中准确计算 PostgreSQL 的三值结果 (TRUE、FALSE、NULL) , 包括 SELECT 列表或 GROUP BY 等值位置。 针对可空列的 NOT IN (SELECT ...) 过滤器也会下推, 并在反解析时加入补偿性保护条件,以保持 PostgreSQL 的行为:包含 NULL 的集合会排除 所有行,而 NULL 探测值仅会在集合为空时通过。当 NOT NULL 声明 证明某个保护条件并非必需时,该条件会被省略。与上述数组形式不同,此保护条件仅 适用于普通过滤条件 (或位于 NOT 之下) ;我们仍不会下推 值位置中的 IN (SELECT ...),也不会下推已分组或聚合的子查询 主体。将列声明为 NOT NULL 可使系统采用开销更低的无保护形式,从而最大化 下推;对于非 Nullable 的 ClickHouse 列,IMPORT FOREIGN SCHEMA 会自动执行此操作。 该推断基于非 NULL 常量、NOT NULL 列,以及对它们执行的基本算术运算 (+-*、一元 -) 。 这些规则假定 ClickHouse 的默认设置为 transform_null_in = 0。pg_clickhouse 会通过 pg_clickhouse.session_settings 参数的默认值, 在每个查询中设置该值, 以防止 ClickHouse server profile 对其进行静默更改。设置 transform_null_in = 1 会破坏所有已下推 IN 的语义。

自定义函数

这些由 pg_clickhouse 创建的自定义函数,可为部分在 PostgreSQL 中没有对应实现的 ClickHouse 函数提供外部查询下推。如果其中任何函数无法下推,则会引发异常。

扩展下推

pg_clickhouse 可识别部分核心扩展和第三方扩展中的函数,并将其下推为 ClickHouse 中对应的等效函数。

re2

所有 re2 extension 运算符和函数都可 1:1 下推到 ClickHouse:

intarray

有一个 intarray 函数可下推至 ClickHouse:

fuzzystrmatch

两个 fuzzystrmatch 函数可下推至 ClickHouse:

下推类型转换

对于兼容的 数据类型,pg_clickhouse 会下推 CAST(x AS bigint) 这类类型转换。 对于不兼容的类型,下推会失败;例如,如果此示例中的 x 是 ClickHouse 的 UInt64, ClickHouse 会拒绝执行该类型转换。 为了将类型转换下推到不兼容的 数据类型,pg_clickhouse 提供了 以下函数。如果这些函数没有被下推,就会在 PostgreSQL 中引发异常。

聚合函数下推

以下 PostgreSQL 聚合函数可下推到 ClickHouse。

自定义聚合函数

这些由 pg_clickhouse 创建的自定义聚合函数,可为部分在 PostgreSQL 中没有对应函数的 ClickHouse 聚合函数提供外部查询下推。如果这些函数中的任何一个无法下推, 就会引发异常。

下推有序集合聚合函数

这些有序集合聚合函数会映射为 ClickHouse 的[参数化 聚合函数]:将其直接参数作为 parameter 传递,并将其 ORDER BY expression 作为 argument。例如,以下 PostgreSQL 查询:
对应的 ClickHouse 查询如下:
请注意,不支持非默认的 ORDER BY 后缀 DESCNULLS FIRST, 使用它们会报错。

自定义有序集合聚合函数

这些由 pg_clickhouse 创建的自定义有序集合聚合函数为部分 ClickHouse [参数化聚合 函数]提供外部查询下推。若其中任何函数无法下推,将引发异常。

自定义有序集合聚合函数

这些由 pg_clickhouse 创建的自定义有序集合聚合函数可为特定的 ClickHouse 参数化聚合函数提供外部查询下推。如果其中任何函数无法下推,则会引发异常。

下推窗口函数

以下 PostgreSQL [窗口函数]可通过包含 OVER (PARTITION BY ... ORDER BY ...) 子句的查询下推到 ClickHouse;适用时还包括窗口帧规范。 排名函数 (row_numberrankdense_rankntilecume_distpercent_rank) 在下推时会省略窗口帧子句,因为 ClickHouse 不支持为这些函数指定窗口帧。

兼容性说明

正则表达式

pg_clickhouse.pushdown_regex 为 true (默认值) 时, pg_clickhouse 会将正则表达式下推为 ClickHouse 中的等效形式, 并尽力保证基本兼容性,但你仍需了解二者之间的差异,以及 pg_clickhouse 如何处理这些差异。
  • PostgreSQL 支持 [POSIX 正则表达式],而 ClickHouse 支持 RE2 正则表达式。请注意两者的行为差异:当正则表达式由 ClickHouse 求值时 (例如,在 WHERE 子句中) ,请使用 RE2;当它由 Postgres 求值时 (例如,在 SELECT 子句中) ,请使用 POSIX。
  • pg_clickhouse 通过将 [Postgres 标志] 置于 ClickHouse 正则表达式前面并放入 (?) 中,来实现下推。例如:
    变成
  • 两者唯一同时支持、因此可在由 ClickHouse 求值时使用的标志有: RE2 仅支持这些标志;请勿使用任何其他 [Postgres 标志]。
  • 下表概述了各种标志 (以及不加标志的情况,此时 与 s 相同) 在匹配换行符和行尾时的影响。请注意,在 Postgres 中,mp 会阻止否定字符类 ([^xyz]) 匹配 换行符,而 ClickHouse 中的对应标志则不会。除此之外, ClickHouse 的行为与 Postgres 相同:
  • 传递给正则表达式函数的任何其他标志都会阻止 该函数被下推。
  • 例外是 regexp_replace(),它还支持 g 标志。当 设置 g 时,pg_clickhouse 会使用 replaceRegexpAll() 而不是 replaceRegexpOne(),并会先移除该标志,再添加其他标志。
  • Postgres 的 regexp_replace() 的 replacement 参数支持使用 \& 来 引用整个匹配;而在 ClickHouse 中,则使用 \0 表示整个 匹配。该函数下推到 ClickHouse 时,务必使用 \0
  • 当没有匹配项时,Postgres regexp_match 会返回 NULL,而 它下推执行的表达式则会返回空数组。请使用 COALESCE() 返回空数组而不是 NULL,以便以兼容的方式比较返回值。 例如:
为避免任何歧义,建议设置 pg_clickhouse.pushdown_regex 以阻止 Postgres 正则表达式下推到 ClickHouse,并使用 re2 extension;对于该扩展,pg_clickhouse 支持将 与 ClickHouse 兼容的 RE2 正则表达式进行直接下推

to_char()

PostgreSQL 中用于 timestamptimestamp with time zoneto_char() 仅在 format argument 为非 NULL 的 string constant,且其中每个 PostgreSQL 关键字 在 ClickHouse 中都有一个逐字节完全一致的对应项时,才会下推到 ClickHouse formatDateTime。 如果 format 是动态的 (不是 Const) ,或者包含任何不支持的关键字或 modifier, 则该调用会回退到 PostgreSQL 本地求值——绝不会在部分翻译的情况下尝试下推, 因此输出会保持与 PG 兼容。 用于 numericinterval 及其他非 timestamp 类型的双参数 to_char() 形式永远不会下推;ClickHouse formatDateTime 仅用于格式化日期时间值。

已转换的关键字

带引号的文本和字面量

"..." 包裹的文本会原样传递,其中任何字面的 % 都会写成 %%,以转义 ClickHouse 的格式说明符前缀。引号外的 \" 也会作为字面量 " 原样传递。在 "..." 内部,反斜杠 只会转义 ";其他反斜杠序列都会被视为字面文本。

作者

David E. Wheeler 版权所有 (c) 2025-2026,ClickHouse
最后修改于 2026年8月18日