Scalar filtering

更新时间:
复制 MD 格式

Vector retrieval often requires scalar filters such as price or category constraints. The optimizer automatically selects the optimal filtering strategy based on filter selectivity.

Filtering strategies

The optimizer selects one of three strategies based on filter selectivity:

  • pre-filtering

  • post-filtering

  • inline-filtering

image

Pre-filtering

When a filter is highly selective, the execution plan first uses a scalar index (such as a BTree index) to build an initial candidate set, then calculates similarity only for vectors in that set.

Post-filtering

When a scalar filter has low selectivity, post-filtering is more efficient. The vector index first retrieves an initial candidate set by similarity, then the scalar filter is applied. A potential issue is that fewer candidates may remain than the top-K value specified in the query.

addresses this with iterative scan: if too few candidates remain after filtering, the system continues vector retrieval until enough candidates are found or a scan limit is reached. To enable iterative scan with an HNSW index:

SET hnsw.iterative_scan = 'relaxed_order';
SET hnsw.max_scan_tuples = 100000;

Parameters:

  • iterative_scan: Controls result ordering by similarity.

    • relaxed_order: Better performance, approximate ordering.

    • strict_order: Strict similarity ordering with higher overhead.

    • off: Disables the feature.

  • max_scan_tuples: Maximum tuples to scan during iterative scan. Prevents unlimited iterations.

Inline-filtering

For medium-selectivity filters where pre-filtering and post-filtering both perform poorly, supports inline-filtering, which combines scalar and vector indexes within a single query.

Supported versions

Supported versions:

  • (minor kernel version 2.0.14.20.44.0 and later)

  • (minor kernel version 2.0.16.13.16.0 and later)

  • (minor kernel version 2.0.17.9.6.0 and later)

  • (minor kernel version 2.0.18.3.2.0 and later)

Note

You can view the minor kernel version in the console or run SHOW polardb_version; to check it. If your cluster does not meet the version requirement, upgrade the minor kernel version.

Example

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;

The execution plan is as follows:

Limit
   ->  Bitmap Filtered Index Scan using idx_items_hnsw on items
         Filter: (category_id = 3)
         TIDs Checked: 40            -- The HNSW index returned 40 TIDs
         Bitmap Hits: 6              -- 6 TIDs matched the bitmap
         ->  Bitmap Index Scan on idx_items_category
               Index Cond: (category_id = 3)

Inline-filtering uses a bitmap pre-filter to skip unnecessary heap fetches, reducing I/O overhead. This strategy is especially effective for queries following the WHERE scalar_col = X ORDER BY vector_col <-> query LIMIT K pattern.

Performance at different filter rates

maintains stable performance across different filter rates. The following table shows which execution plan is selected at each rate:

filter_rate

Performance improvement

Execution plan

0.001

No change

pre-filtering

0.1

No change

post-filtering

0.5

No change

post-filtering

0.9

No change

post-filtering

0.95

No change

inline-filtering

0.98

1.4x

inline-filtering

0.99

2.9x

inline-filtering

0.995

4.3x

inline-filtering

0.999

No change

post-filtering