在实际生产业务中,向量检索往往需要结合标量过滤条件(例如“查找所有类似的鞋子但价格不超过100”)。PolarDB PostgreSQL版的优化器会自动根据过滤条件的选择率选择最优的过滤策略。
过滤策略
PolarDB PostgreSQL版的优化器会自动根据过滤条件的选择率选择以下三种过滤策略之一:
Pre-Filtering
Post-Filtering
Inline-Filtering
Pre-Filtering
当过滤之后剩下的数据很少时,执行计划会使用高效的标量索引(如BTree索引)筛选候选集,然后再使用向量字段执行相似度计算,得到最终的候选集。
Post-Filtering
若标量过滤条件并不能筛选很多的数据,则Post-Filtering效率更高。先使用向量索引进行相似度计算,得到候选集之后再按照标量过滤条件进行筛选。Post-Filtering可能出现向量索引返回的候选集经过标量过滤之后,剩下的数据量少于SQL要求的Top-K。
PolarDB PostgreSQL版支持Iterative Scan,如果在标量筛选之后剩下的候选集不足,可以继续执行向量检索,直到候选集足够或者扫描的数据量超限。以HNSW索引为例,使用方式如下:
SET hnsw.iterative_scan = 'relaxed_order';
SET hnsw.max_scan_tuples = 100000;参数说明:
iterative_scan:控制返回的数据集是否严格按照相似度排序。relaxed_order:性能更好。strict_order:保证严格按照相似度的顺序,开销更大。off:关闭功能。
max_scan_tuples:即使开启了Iterative Scan,最大扫描的数据量,避免无限制地迭代。
Inline-Filtering
在过滤条件的选择性不多也不少的中间地段,Pre-Filtering和Post-Filtering的性能会剧烈下降。PolarDB PostgreSQL版支持Inline-Filtering,可以在一个查询里同时使用标量索引和向量索引。
适用范围
Inline-Filtering支持的PolarDB PostgreSQL版的版本如下:
PostgreSQL 14(内核小版本2.0.14.20.44.0及以上)
PostgreSQL 16(内核小版本2.0.16.13.16.0及以上)
PostgreSQL 17(内核小版本2.0.17.9.6.0及以上)
PostgreSQL 18(内核小版本2.0.18.3.2.0及以上)
操作示例
SELECT id, category_id, embedding, embedding <-> '[50,50,50]' AS distance
FROM items
WHERE category_id = 3 -- B-Tree bitmap filter
ORDER BY embedding <-> '[50,50,50]' -- HNSW ordered scan
LIMIT 10;查看执行计划如下:
Limit
-> Bitmap Filtered Index Scan using idx_items_hnsw on items
Filter: (category_id = 3)
TIDs Checked: 40 -- HNSW返回了40个TID
Bitmap Hits: 6 -- 6个命中bitmap
-> Bitmap Index Scan on idx_items_category
Index Cond: (category_id = 3)Inline Filtering在标量过滤 + 向量排序的混合查询场景下,通过Bitmap预过滤避免了大量无效的Heap Fetch,显著减少I/O开销。特别适合WHERE scalar_col = X ORDER BY vector_col <-> query LIMIT K这类典型的向量检索 + 业务过滤查询模式。
不同过滤率下的性能表现
在不同filter_rate条件下,PolarDB PostgreSQL版可以保持稳定的性能表现。各过滤率下的执行计划选择如下表所示:
filter_rate | 性能提升 | 执行计划 |
0.001 | 不变 | Post-Filtering |
0.1 | 不变 | Post-Filtering |
0.5 | 不变 | Post-Filtering |
0.9 | 不变 | Post-Filtering |
0.95 | 不变 | Inline-Filtering |
0.98 | 1.4x | Inline-Filtering |
0.99 | 2.9x | Inline-Filtering |
0.995 | 4.3x | Inline-Filtering |
0.999 | 不变 | Pre-Filtering |