帮你快速理解、总结文档立即下载

高性能正则函数

最近更新时间:2026-07-21 09:53:00

我的收藏

功能概述

PostgreSQL 内置的 POSIX 正则实现基于 NFA/ 回溯,遇到复杂模式或长字符串时容易触发指数级回溯(catastrophic backtracking),成为 CPU 热点。tencentdb_regex 扩展将 Google RE2 引擎(deterministic 自动机、有界最坏复杂度)打包进云数据库 PostgreSQL,提供与主干 regexp_* 语义对齐但性能更稳定的替代函数。

前置条件

PostgreSQL 18,版本 ≥ v18.4_r1.10。

使用限制

正则语法遵循 RE2 语法(PCRE 兼容子集,不支持反向引用 \\1 与部分 look-around)。若正则中依赖这些高级特性,请继续使用主干 regexp_*。
tencentdb_regex 的 flags 语义与主干 regexp_* 一致(g、i、m、s、x 等),但底层交给 RE2,实现细节可能微小差异。
schema 为 tencentdb,建议将 tencentdb 加入 search_path 或显式写 tencentdb.regexp_xxx。

创建插件

CREATE EXTENSION tencentdb_regex;

-- 可选:加入搜索路径以便直接写 regexp_replace(...)
SET search_path = tencentdb, public;

SELECT extname, extversion FROM pg_extension WHERE extname = 'tencentdb_regex';

函数清单

以下函数均有 tencentdb.regexp_* 与 tencentdb_regexp_* 两种命名。

regexp_replace

tencentdb.regexp_replace(source text, pattern text, replacement text)
RETURNS text;
tencentdb.regexp_replace(source text, pattern text, replacement text, flags text)
RETURNS text;
作用等价于主干 regexp_replace。flags 常用值:
g:全局替换(默认仅第一处)。
i:忽略大小写。
m:多行模式(^/$ 匹配行首/行尾)。

regexp_match / regexp_matches

tencentdb.regexp_match(source text, pattern text) RETURNS text[];
tencentdb.regexp_match(source text, pattern text, flags text) RETURNS text[];

tencentdb.regexp_matches(source text, pattern text) RETURNS SETOF text[];
tencentdb.regexp_matches(source text, pattern text, flags text) RETURNS SETOF text[];
regexp_match 返回首个匹配的捕获组数组;regexp_matches 是 SRF,返回所有匹配(配合 g flag)。

regexp_split_to_array / regexp_split_to_table

tencentdb.regexp_split_to_array(source text, pattern text) RETURNS text[];
tencentdb.regexp_split_to_array(source text, pattern text, flags text) RETURNS text[];

tencentdb.regexp_split_to_table(source text, pattern text) RETURNS SETOF text;
tencentdb.regexp_split_to_table(source text, pattern text, flags text) RETURNS SETOF text;
按 pattern 分割字符串。前者返回数组,后者以 SRF 返回每段。

regexp_extract

tencentdb.regexp_extract(source text, pattern text, group_id integer) RETURNS text;
tencentdb.regexp_extract(source text, pattern text, group_id integer, flags text) RETURNS text;
返回首次匹配中第 group_id 个捕获组(0表示整段匹配)。无匹配或该组未参与匹配时返回 NULL。

regexp_count

tencentdb.regexp_count(source text, pattern text) RETURNS integer;
tencentdb.regexp_count(source text, pattern text, flags text) RETURNS integer;
返回 pattern 在 source 中的匹配次数。

regexp_like

tencentdb.regexp_like(source text, pattern text) RETURNS boolean;
tencentdb.regexp_like(source text, pattern text, flags text) RETURNS boolean;
判定是否存在至少一次匹配。等价于 source ~ pattern / source ~* pattern,但走 RE2。

使用示例

CREATE EXTENSION IF NOT EXISTS tencentdb_regex;
SET search_path = tencentdb, public;

-- 1) 全局替换(RE2 版),大小写不敏感
SELECT regexp_replace('Hello World, hello RE2', 'hello', 'hi', 'gi');

-- 2) 抽取所有 URL 主机部分
SELECT regexp_matches(
'see http://a.com and https://b.io/xyz',
'(?i)https?://([^/\\s]+)', 'g');

-- 3) 分割为表
SELECT regexp_split_to_table('a1b22c333d', '[0-9]+') AS part;

-- 4) 抽取第 N 个分组
SET search_path = tencentdb, public;
SELECT regexp_extract('user_id=42; name=alice',
'user_id=([0-9]+); name=([a-z]+)', 2);
-- alice

-- 5) 计数
SELECT regexp_count('aaa bbb aa cc aaaa', 'a+');

-- 6) 存在性
SELECT regexp_like('info@tencent.com', '^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$');
与主干函数并存:由于均在 tencentdb schema 下,业务可以按需选择,例如:
-- 明确走 RE2
SELECT tencentdb.regexp_replace(col, pat, rep, 'g') FROM tbl;

-- 依然使用主干
SELECT pg_catalog.regexp_replace(col, pat, rep, 'g') FROM tbl;