PostgreSQL中能否修改Levenshtein函数的最大字符限制?
解决PostgreSQL中levenshtein函数255字符长度限制问题
问题描述
执行以下查询时触发错误:
ERROR: levenshtein argument exceeds maximum length of 255 characters
查询语句:
SELECT levenshtein('xxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY');
PostgreSQL官方文档明确levenshtein函数默认限制源/目标字符串长度为255字符,但业务需要支持任意长度的字符串,需找到修改该限制的方法。
可行解决方案
1. 修改fuzzystrmatch扩展源码重新编译
levenshtein的长度限制是在扩展源码中硬编码的,具体定义在fuzzystrmatch.c文件里的MAX_LEVENSHTEIN_STRLEN宏(默认值255)。操作步骤:
- 下载对应PostgreSQL版本的源码包,定位到
contrib/fuzzystrmatch/fuzzystrmatch.c文件 - 修改
#define MAX_LEVENSHTEIN_STRLEN 255为所需数值(如1024或更大) - 重新编译安装该扩展:
cd contrib/fuzzystrmatch make clean make make install - 重启PostgreSQL服务,重新创建扩展(若已存在需先删除再创建)
注意:此方式需要服务器编译权限,且PostgreSQL升级时需重复修改编译步骤,维护成本较高。
2. 使用自定义实现替代内置函数
若无法修改源码,可自行实现支持长字符串的Levenshtein距离函数,以下是PL/pgSQL的简化实现示例(性能略逊于内置C函数,但无长度限制):
CREATE OR REPLACE FUNCTION levenshtein_long(a text, b text) RETURNS integer AS $$ DECLARE len_a integer := length(a); len_b integer := length(b); d integer[][] := array_fill(0, array[len_a + 1, len_b + 1]); i integer; j integer; BEGIN IF len_a = 0 THEN RETURN len_b; END IF; IF len_b = 0 THEN RETURN len_a; END IF; FOR i IN 0..len_a LOOP d[i][0] := i; END LOOP; FOR j IN 0..len_b LOOP d[0][j] := j; END LOOP; FOR i IN 1..len_a LOOP FOR j IN 1..len_b LOOP IF substring(a from i for 1) = substring(b from j for 1) THEN d[i][j] := d[i-1][j-1]; ELSE d[i][j] := least( d[i-1][j] + 1, -- 删除 d[i][j-1] + 1, -- 插入 d[i-1][j-1] + 1 -- 替换 ); END IF; END LOOP; END LOOP; RETURN d[len_a][len_b]; END; $$ LANGUAGE plpgsql IMMUTABLE;
使用时直接调用levenshtein_long('长字符串1', '长字符串2')即可,注意长字符串会占用更多内存,性能会有所下降。
3. 字符串截断折中方案(仅临时应急,不推荐)
若业务可接受精度损失,可先将长字符串截断到255字符再计算,但会丢失尾部信息,结果可能不准确:
SELECT levenshtein(left('xxxxxxxx', 255), left('超长目标字符串', 255));
内容的提问来源于stack exchange,提问作者Nullify
相关产品推荐
相关产品推荐

