资讯动态

Windows下VS2008编译zhparser:PostgreSQL中文全文检索落地指南

发布时间:2026/9/25 11:31:56 来源:尧图企业网站定制
简介这是一份适用于 WindowsVS2008 环境的 PostgreSQL 中文分词扩展 zhparser 安装程序包面向需要在 Windows 下配置中文全文检索的开发者尤其适合不熟悉 makefile、希望避开 Cygwin 和 MinGW 交叉编译流程的初学者与运维人员。压缩包内含 scws 与 zhparser 的完整 VS2008 编译工程包括 14 个 C 源码与 14 个头文件、多个工程配置文件以及编译生成的 DLL、LIB 等可执行组件另有 SQL、INI、CONTROL 等扩展安装与运行配置文件共 138 个文件打包后约 11.19MB。资源已有 1601 人浏览学习。包内完整记录了 Windows 移植过程中的关键排错经验从头文件编码转换、自建 VS 工程链接 PostgreSQL 库到扩展注册时控制文件和 DLL 放置位置、函数导出声明调整、词典与 ini 配置应放入 tsearch_data 目录等。下载这份资源即可获得编译好的组件与工程模板能够帮助开发者在 Windows 环境下快速完成 zhparser 部署实现中文分词检索避免重复踩坑。1. 当 PostgreSQL 遇上中文分词Windows 环境绕不开 zhparser当 PostgreSQL 表里存的是中文标题全文检索一查一个空的时候问题基本出在分词这一层。PG 自带的 parser 按空格和标点切词中文句子没有空格于是“南京市长江大桥”会被当成一个整 tokentsquery想命中“长江大桥”完全不可能。zhparser 是 PostgreSQL 的中文分词扩展底层复用 SCWS 分词引擎能把句子切成“南京 / 南京市 / 长江 / 大桥 / 长江大桥”这些可检索词再对接 PG 原生的 tsvector/tsquery属于目前 Windows 上少有的能直接进生产的中文检索方案。Linux 上一条make install就算了事但标题里这个 windows VS2008 环境没有捷径SCWS 和 zhparser 都得手工编成 DLL词典路径、服务账户权限、编译器版本全要自己确认。这篇文章讲的正是这套环境从源码到可用的完整落地路径。2. 装 zhparser 前先核对 VS2008 和 PostgreSQL 版本ABI 匹配是第一道关卡2.1 编译器版本就是 PostgreSQL 的 ABI 版本PG 的扩展是以 DLL 形式被服务进程加载的。服务进程启动加载 zhparser.dll 时会做模块 magic 校验调用的入口函数和内存分配也都依赖同一个 C Runtime。如果 PostgreSQL 官方 Windows 二进制是用 VS2008VC9编的而你手里拿的 zhparser.dll 是更高版本编译器编的轻则加载失败重则服务进程崩溃。标题特意把 VS2008 写出来不是怀旧而是说明这套安装程序面向的是 PostgreSQL 9.x 早期的官方二进制环境。常见对应关系大致如下PostgreSQL 版本官方 Windows 二进制常见编译工具zhparser 编译建议9.0 ~ 9.3VS2008VC9按本教程用 VS20089.4 ~ 9.6VS2010 / VS2013 交替期优先用与 PG 相同版本的工具链10VS2015 / VS2017 / VS2019不建议再用 VS2008 硬编判断依据不是看安装包年份而是看 PG 自带开发组件里的导入库格式。最稳妥的做法是先确认你服务器的 PG 大版本再决定要不要按标题里的 VS2008 流程走。如果线上是 PG 12拿着 VS2008 编的 zhparser.dll 去加载loader 几乎必然翻车。2.2 装之前先确认三件事版本、位数、开发头文件很多 postgresql 安装教程只教你双击下一步恰恰漏了最关键的 Development Components。没有它include\server\postgres.h和lib\postgres.lib都不存在后续编译直接失败。先用命令把版本和位数问清楚# 在 PG 安装目录下执行不要只敲 pg_configPATH 里往往没有它 C:\Program Files\PostgreSQL\9.3\bin\pg_config.exe --version # 确认开发组件是否装了 Test-Path C:\Program Files\PostgreSQL\9.3\include\server\postgres.h Test-Path C:\Program Files\PostgreSQL\9.3\lib\postgres.lib版本输出类似PostgreSQL 9.3.25。位数看安装目录C:\Program Files\PostgreSQL下通常是 64 位C:\Program Files (x86)\PostgreSQL下是 32 位也可以打开任务管理器看postgres.exe进程的平台列。64 位 PG 必须配 64 位 zhparser.dll这是后面最常见的一个坑。如果 5432 端口被别的进程占了先netstat -ano | findstr 5432找到 PID再决定结束还是换端口免得后面测试时怎么查都连不上。提示下载 PostgreSQL 时别默认拿最新版尤其当你是照着旧项目文档做。先看生产环境里跑的是哪个大版本再决定编译工具链。2.3 别拿新版 PG 硬套 VS2008 编译产物网上能搜到一些现成的 zhparser.dll 下载包来源不明且不标注编译器版本。这里的关键不是文件名而是 DLL 的导入符号和 CRT 依赖。下载下来先用 Dependencies 工具或dumpbin /dependents zhparser.dll看一眼依赖确认它引用的 msvcr90.dllVC9还是 msvcr140.dllVC15。如果系统里只有 VC9 运行库而 DLL 要的是高版本 msvcp那基本可以直接放弃省得浪费时间排错。结论是本教程默认目标环境为 PostgreSQL 9.x 的官方 Windows 安装包配套 VS2008 工具链。版本核对这一步不是走过场它决定了后面所有工程配置。3. 用 VS2008 编译 SCWS先把分词引擎做成静态库3.1 zhparser 自己不分词SCWS 才是核心zhparser 只是 PG 和 SCWS 之间的桥真正的分词逻辑在 SCWS 里。SCWS 官方分发的是 Linux 源码包Windows 下没有现成的 VS 工程文件。这意味着要把 SCWS 的核心源码手工编成静态库libscws.lib等编译 zhparser.dll 时再链进 zhparser让最终产物只依赖 PG 自身的运行库。把 SCWS 1.2.x 源码解开后在 VS2008 里新建一个 Win32 Static Library 工程把libscws目录下的 .c 和 .h 全部加进去。注意 VS2008 默认没有stdint.h和stdbool.hSCWS 源码会用 C99 的几个标准头直接编译会报找不到头文件。常见做法是安装 VS2008 SP1再从 Windows SDK 里找一份兼容的stdint.h放到工程 include 目录这一步不做后面全是语法错误。提示VS2008 的“解决方案平台”默认只有 Win32。要编 64 位库得在 VS2008 安装程序里勾选 x64 编译工具否则后面链接 zhparser.dll 时会卡在找不到 x64 linker。3.2 编译 SCWS 静态库的命令与关键宏我一般不走 IDE 界面直接用 VS2008 命令行工具vcvarsall.bat切好环境再编译出错信息更直观。以下命令适用于 32 位目标64 位把vcvarsall.bat参数改成 x64 即可mkdir C:\zhparser-build cd C:\zhparser-build set SCWS_SRCC:\scws-1.2.3\libscws cl /c /O2 /MD /D WIN32 /D _CRT_SECURE_NO_WARNINGS /D SCWS_UTF8 %SCWS_SRC%\*.c lib /OUT:libscws.lib *.obj这里三个参数都不能省。/MD让 SCWS 静态库使用动态 CRT这和 PG 官方二进制保持一致如果改成/MTzhparser.dll 加载后可能出现内存分配混乱或字符串处理异常。SCWS_UTF8对应 SCWS 在 Linux 下configure --enable-utf8的开关漏掉它后面分词会按 GBK 处理中文结果全是乱码。_CRT_SECURE_NO_WARNINGS是为了压掉 VC9 对strcpy一类函数的安全警告不然编译输出几百行 warning真正有用的 error 被淹掉。cl /c ... *.c编译完成后lib /OUT:libscws.lib *.obj把所有目标文件打包成静态库。如果 lib 命令提示找不到 obj说明前面某个 .c 编译失败回头看编译器输出里第一个 error通常是 stdint.h 缺失先把 3.1 里的头文件补上。3.3 SCWS 词典先放好位置后面要用SCWS 运行时需要两个文件dict.utf8.xdb是词典rules.utf8.ini是规则文件。这两个文件一般都在 SCWS 源码包根目录下。先在 PG 安装目录下建一个清晰的文件目录把词典放进去mkdir C:\Program Files\PostgreSQL\9.3\share\zhparser copy C:\scws-1.2.3\dict.utf8.xdb C:\Program Files\PostgreSQL\9.3\share\zhparser\ copy C:\scws-1.2.3\rules.utf8.ini C:\Program Files\PostgreSQL\9.3\share\zhparser\目录名不要用中文路径里不要有空格之外的特殊字符。SCWS 在 Windows 下对非常规路径的处理很弱这一步省事后面能躲开一堆玄学报错。3.4 静态库是否编译成功的自检用 lib 工具可以直接查看静态库里包含了哪些目标文件lib /LIST C:\zhparser-build\libscws.lib输出里能看到scws.obj、scws_ini.obj、dict.obj这一类名字说明打包成功。如果这里什么都不显示回头看编译那一步是不是只生成了 obj 没打包成功。也可以顺手确认一下libscws.lib的文件大小SCWS 核心库通常在几百 KB 级别太小说明可能只编进去了一部分源码链接 zhparser 时会出现未解析符号。4. 编译 zhparser.dll 并部署到 PostgreSQL从工程设置到 CREATE EXTENSION4.1 建 zhparser DLL 工程的 include 路径与预处理器配置zhparser 源码包里核心文件是 zhparser.c其余 sql 和 control 文件在sql目录下。编译 zhparser.c 需要两类头文件PG 的 server 开发头文件和 SCWS 的头文件。PG 的 include 路径不是只有include\server一个include\server\port\win32也要加否则编译器找不到 Windows 平台相关的内部头文件。用 VS2008 新建 Win32 DLL 工程后在工程属性里把以下目录填进 C/C 附加包含目录C:\Program Files\PostgreSQL\9.3\include\server C:\Program Files\PostgreSQL\9.3\include\server\port\win32 C:\Program Files\PostgreSQL\9.3\include C:\scws-1.2.3\libscws也可以跳过 IDE直接用命令行编译链接这样整个流程能写进部署脚本set PG_ROOTC:\Program Files\PostgreSQL\9.3 set SCWS_SRCC:\scws-1.2.3\libscws cl /c /O2 /MD /D WIN32 /D _CRT_SECURE_NO_WARNINGS ^ /I %PG_ROOT%\include\server /I %PG_ROOT%\include\server\port\win32 ^ /I %PG_ROOT%\include /I %SCWS_SRC% C:\zhparser-src\zhparser.c link /DLL /OUT:zhparser.dll zhparser.obj C:\zhparser-build\libscws.lib ^ %PG_ROOT%\lib\postgres.lib/I的顺序有讲究include\server必须排在前面因为 zhparser.c 里#include postgres.h是直接从 server 头目录找的。postgres.lib是 PG 提供的导入库缺了它链接阶段会报一堆未解析的外部符号。如果%PG_ROOT%\lib\postgres.lib不存在回到 2.2 重新装开发组件不要自己从网上找替代文件。4.2 文件部署DLL、控制文件、SQL 脚本编译得到 zhparser.dll 后部署一共涉及三个目录。lib 目录放 DLLshare\extension 放扩展控制文件和 SQL 脚本share\zhparser 放 SCWS 词典。用命令复制copy C:\zhparser-build\zhparser.dll C:\Program Files\PostgreSQL\9.3\lib\ copy C:\zhparser-src\sql\zhparser.control C:\Program Files\PostgreSQL\9.3\share\extension\ copy C:\zhparser-src\sql\zhparser--*.sql C:\Program Files\PostgreSQL\9.3\share\extension\文件目标目录作用zhparser.dll%PG_ROOT%\lib扩展本体服务进程加载zhparser.control%PG_ROOT%\share\extension扩展元信息含 default_versionzhparser--版本.sql%PG_ROOT%\share\extension创建扩展对象的脚本dict.utf8.xdb / rules.utf8.ini%PG_ROOT%\share\zhparserSCWS 分词词典必须确认zhparser.control里的default_version和 SQL 脚本的命名一致。比如 control 文件写default_version 2.1那 share\extension 目录下就必须有zhparser--2.1.sql。版本对不上时CREATE EXTENSION会直接报没有安装脚本这在 5.3 里细说。4.3 数据库里启用 zhparser 并完成第一次分词部署完成后重启 PostgreSQL 服务然后在数据库里执行CREATE EXTENSION zhparser; CREATE TEXT SEARCH CONFIGURATION chinese (PARSER zhparser); ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple; SELECT * FROM ts_parse(zhparser, 南京市长江大桥);ts_parse是直接调用解析器绕开搜索配置适合验证分词本身有没有生效。ALTER TEXT SEARCH CONFIGURATION里映射的 n、v、a、i、e、l 是 zhparser 输出的词性标签分别对应名词、动词、形容词、成语、习用语、叹词。这里只映射这六类是因为副词、助词、标点一类内容进 tsvector 只会拉低检索精度不映射它们就等于默认丢弃。如果ts_parse返回空集或报错先看 PG 日志通常卡在词典路径。zhparser 的词典路径可以用参数指定9.3 环境直接写进postgresql.confzhparser.dict_path C:/Program Files/PostgreSQL/9.3/share/zhparser注意路径里的反斜杠要改成正斜杠。改完重启服务再用上面的 SQL 验证一次。PG 9.4 之后也可以用ALTER SYSTEM SET zhparser.dict_path ...效果一样。4.4 造一张表把全文检索索引建起来扩展装完只是第一步真正投入使用需要建全文检索索引CREATE TABLE news ( id serial PRIMARY KEY, title text ); INSERT INTO news (title) VALUES (南京市长江大桥开始维修), (长江流域防汛形势严峻), (南京本地企业招聘运维工程师); CREATE INDEX news_title_tsv ON news USING GIN (to_tsvector(chinese, title)); SELECT id, title FROM news WHERE to_tsvector(chinese, title) to_tsquery(chinese, 南京 长江);to_tsvector按 chinese 配置分词GIN 索引让全文检索走索引而不是全表扫。左边是 tsvector右边是 tsquery表示 AND。到这里 zhparser 就算真正接进 PG 的全文检索体系了后面再谈调参。5. Windows 下 zhparser 安装的 5 个典型翻车点与排查顺序5.1 明明是 64 位 PG却报“不是有效的 Win32 应用程序”现象CREATE EXTENSION或首次调用分词时报ERROR: could not load library C:/Program Files/PostgreSQL/9.3/lib/zhparser.dll: %1 不是有效的 Win32 应用程序。原因PG 是 64 位而 zhparser.dll 是 32 位。VS2008 默认工程平台是 Win32编译出来的是 32 位 DLL64 位 PG 加载它时直接把 PE 文件头拒了。解决回到 SCWS 静态库和 zhparser 两个工程把解决方案平台切到 x64再按第 3、4 章的命令重新编译。VS2008 要提前装好 x64 编译工具否则平台列表里根本没有 x64。验证方式是编译完看一眼生成目录里的 DLL 大小64 位的 zhparser.dll 通常比 32 位的大一圈。5.2 报“找不到指定的模块”其实不是缺 zhparser.dll现象同样的加载错误但后面跟的是“找不到指定的模块”文件明明就在 lib 目录里。原因zhparser.dll 不是独立运行的它依赖 libscws 和 VC9 运行库。如果 zhparser 链接的是 SCWS 动态库那libscws.dll必须在系统搜索路径里如果服务器没装过 VC9 运行库msvcr90.dll缺失也会爆这条。解决按第 4 章的做法把 SCWS 静态链进 zhparser.dll让最终产物不依赖 libscws 这个外部 DLL。另外在服务器上装一遍vcredist_x64.exe或vcredist_x86.exe版本选 VS2008 SP1也就是 VC9 运行库。装完重启 PostgreSQL 服务再试。5.3 CREATE EXTENSION 报 no installation script现象ERROR: extension zhparser has no installation script nor update path for version 2.1。原因zhparser.control 文件和 zhparser--版本.sql 文件没有同时放到share\extension目录或者 control 文件里的default_version和 SQL 文件名不一致PG 找不到对应版本的安装脚本。解决检查 extension 目录下实际有哪些文件dir C:\Program Files\PostgreSQL\9.3\share\extension\zhparser* type C:\Program Files\PostgreSQL\9.3\share\extension\zhparser.control确认default_version的值和zhparser--2.1.sql中间的版本号完全一致。版本号是源码包自己定的我见过因为源码包是 2.2 而 control 文件写 2.1 导致装不上的情况改 control 文件或复制对应版本 SQL 文件就能解决。5.4 ts_parse 返回空集或乱码先查字典路径和字符集现象SELECT * FROM ts_parse(zhparser, 南京市长江大桥)返回零行或者分出来的词完全不是预期内容。原因三种情况最常见。第一zhparser.dict_path没设置或指向的目录里没有dict.utf8.xdb第二SCWS 静态库编译时没定义SCWS_UTF8词典按非 UTF8 方式读取第三数据库本身编码不是 UTF8。解决先查SHOW server_encoding数据库编码如果不是 UTF8最好新建 UTF8 库再测。确认编码后把zhparser.dict_path指向 share\zhparser 目录重启 PG 服务。如果依旧乱码回第 3 章重新编译 libscws.lib确认命令行里带了/D SCWS_UTF8这一步漏掉最容易在 Windows 上翻车。5.5 服务账户读不到词典psql 正常但程序调用分词为空现象psql 里手工执行分词一切正常但通过应用接口调用时返回空或者分词缺失PG 日志里能看到打开词典失败。原因psql 运行时用的是你当前登录用户而 PG 服务进程默认以 Network Service 账户运行。词典放在C:\Users\某个用户\...目录下时Network Service 根本没权限访问。这类问题最玄因为表面看配置都对。解决把词典统一放到 PG 安装目录内比如C:\Program Files\PostgreSQL\9.3\share\zhparser同时手动给该目录的 Network Service 账户加读取权限。生产环境建议把 PG 服务账户改成专用账户并授权而不是继续用默认账户硬扛。6. 调 multi 参数、自建词典把 zhparser 转成能上线的中文检索6.1 三个必调的 zhparser 参数zhparser 有一组 multi 系列参数控制是否输出组合词。默认分词把“长江大桥”切成“长江”和“大桥”但很多场景需要“长江大桥”作为一个整体词召回。上线前我一般会调整这三个参数作用建议值zhparser.multi_short输出单字词和二字词组合truezhparser.multi_duality输出二字叠词形式的组合truezhparser.punctuation_ignore忽略标点避免把标点作为 tokentrue配置方式在 PG 9.4 之后可以动态生效ALTER SYSTEM SET zhparser.multi_short true; ALTER SYSTEM SET zhparser.punctuation_ignore true; SELECT pg_reload_conf();9.3 不支持 ALTER SYSTEM直接改postgresql.conf里对应行同样重启后生效。multi 参数开太多会让 tsvector 体积变大索引膨胀明显所以按业务需要开不要全部堆上。6.2 验证检索效果的几条 SQL看分词是否满足需求直接看 tsvector 即可SELECT to_tsvector(chinese, 南京市长江大桥); -- 期望结果里同时出现 南京、长江、大桥实际检索时习惯从 MySQL 转过来的同学容易下意识写LIKE %词%但 zhparser 接的是 PG 的 tsquery 体系两边语法差异不小SELECT id, title FROM news WHERE to_tsvector(chinese, title) to_tsquery(chinese, 南京 长江);6.3 自定义词典把行业词补进去zhparser 支持通过zhparser.extra_dicts加载自定义词典文件适合补齐人名、产品名、专业术语这类 SCWS 词库里没有的词。自定义词典是文本文件UTF-8 无 BOM每行一个词# custom_dict.txt 智慧水务 流域治理 运维工程师配置方式与 dict_path 相同多个词典文件用逗号分隔zhparser.extra_dicts C:/Program Files/PostgreSQL/9.3/share/zhparser/custom_dict.txt改完重启 PG 服务再执行 6.2 的验证 SQL确认新词能出现在 tsvector 结果里。注意别放 Windows 的 UTF-8 带 BOM 文件SCWS 读取时会把 BOM 当成词的一部分直接导致自定义词全部失效。我在这套老环境上栽过两次一次是手滑把/MD改成/MT服务进程偶发崩溃查了一晚上另一次是词典路径里带了中文目录名SCWS 一直打不开文件。从那以后固定用英文路径、统一/MD编译参数每次部署完先跑一遍ts_parse再交给业务方基本没再翻过车。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑