在构建现代应用程序时,开发者常常面临一个困境:用户需要实时搜索(Real-time Search)与分析(Analytics)功能,但这通常意味着要在数据库的一致性(Consistency)与性能(Performance)之间做出取舍。虽然PostgreSQL内置了全文检索功能,但其在处理中文分词和排序(Ranking)时存在局限性,这也催生了丰富的插件生态。近期,被誉为“PostgreSQL用户的ElasticSearch替代品”的搜索引擎插件ParadeDB发布了v0.20.0版本,带来了更简洁的API和显著的性能提升。
搜索聚合:无缝衔接分析与事务
现代应用不仅需要搜索,更需要在搜索结果上进行分面(Facets)、计数、直方图等聚合分析。传统方案若基于事务型数据库构建,往往需要复杂的查询规划。ParadeDB 0.20.0将搜索聚合(Search Aggregations)提升为“一等公民”,通过新的pdb.agg()函数提供支持。
该函数有两种使用方式:
- 作为聚合函数:直接返回聚合结果。
- 作为窗口函数:在返回TopN搜索结果的同时,提供聚合结果。
这两种方式都将大部分计算工作下推至ParadeDB索引内部执行,避免了多重查询或手动聚合的麻烦。其性能在超大规模数据集上表现卓越,对于超过4000万条结果的搜索分面,性能比传统方法快了一个数量级。
基础使用示例:
-- 简单的计数聚合,会被自动优化
SELECT count(*) FROM mock_items WHERE description ||| 'shoes';
结合窗口函数与复杂JSON API的示例:
SELECT id, description,
pdb.agg('{"terms": {"field": "rating"}}') AS facets
FROM mock_items
WHERE description ||| 'shoes'
ORDER BY rating DESC
LIMIT 2;
在底层,这些查询利用BM25索引进行全文搜索,并结合列式分析技术,可在保持与事务数据完美一致性的同时,实现跨数百万文档的亚秒级聚合计算。
v2 API:简化配置,提升开发体验
如果强大的功能难以使用,其价值就会大打折扣。v0.20.0将更直观的v2 API设为默认,其核心优势是消除了令人头疼的模式重复(Schema Duplication)问题。
与需要单独定义映射的Elasticsearch不同,ParadeDB v2 API能够直接从PostgreSQL表模式中推断出大部分索引模式。用户只需在创建索引时,于语句中直接定义文本处理和搜索行为即可。
改进后的索引创建示例:
CREATE INDEX search_idx ON mock_items
USING bm25 (id,
title,
(description::pdb.simple('stemmer=english',
'stopwords_language=english')),
category::pdb.literal)
WITH (key_field='id');
搜索语法也得到增强,引入了新的合取运算符&&&和析取运算符|||,并简化了加权等常用功能的调用方式,让查询编写更加清晰直接。
写入性能:为实时更新而优化
传统的搜索引擎底层常使用不可变数据结构,导致单行更新会产生显著的写入放大(Write Amplification),性能开销大。ParadeDB v0.20.0针对现实应用中常见的“单行更新流”场景进行了深度优化。
其核心是基于LSM引擎的两项优化:可变段(Mutable Segments)和后台合并(Background Merging)。
- 可变段:作为一个专为写入优化的小型缓冲区,临时存储新行指针,彻底避免写入放大。
- 后台合并:将缓冲区序列化及段合并等耗时操作移至后台异步执行,不阻塞前端写入。
自0.19.0引入这些优化以来,ParadeDB的单行更新性能已提升两个数量级以上,使其能够真正适应高并发的实时事务性搜索场景。
小结
ParadeDB v0.20.0通过提供强大的原生搜索聚合、极大简化的v2 API以及革命性的写入性能,进一步巩固了其作为ElasticSearch替代方案的地位。它让重视事务一致性与运维简单性的团队,能够在PostgreSQL数据库内部获得现代化的搜索与分析能力,无需再维护复杂的独立搜索系统,从而降低总体拥有成本与开发复杂度。