You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+85Lines changed: 85 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -451,6 +451,91 @@ Use [partitioning](https://www.postgresql.org/docs/current/ddl-partitioning.html
451
451
CREATETABLEitems (embedding vector(3), category_idint) PARTITION BY LIST(category_id);
452
452
```
453
453
454
+
##Iterative Search
455
+
456
+
*Unreleased*
457
+
458
+
With approximate indexes, queries with filtering can return less results (due to post-filtering).
459
+
460
+
Starting with 0.8.0, you can enable iterative search. If too few results from the initial index scan match the filters, the scan will resume until enough results are found (or it reaches`hnsw.max_search_tuples` or`ivfflat.max_probes`). This can significantly improve recall.
461
+
462
+
There are two modes for iterative search: strict and relaxed (due to the streaming nature of Postgres executor).
463
+
464
+
Strict ensures results are in the exact order by distance
465
+
466
+
```sql
467
+
SEThnsw.iterative_search= strict_order;
468
+
```
469
+
470
+
Relaxed allows results to be slightly out of order by distance, but provides better recall
471
+
472
+
```sql
473
+
SEThnsw.iterative_search= relaxed_order;
474
+
# or
475
+
SETivfflat.iterative_search= relaxed_order;
476
+
```
477
+
478
+
Note: IVFFlat only supports relaxed order for iterative search
479
+
480
+
With relaxed ordering, you can use a[materialized CTE](https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-CTE-MATERIALIZATION) to get strict ordering
481
+
482
+
```sql
483
+
WITH relaxed_resultsAS MATERIALIZED (
484
+
SELECT id, embedding<->'[1,2,3]'AS distanceFROM itemsWHERE category_id=123ORDER BY distanceLIMIT5
485
+
)SELECT*FROM relaxed_resultsORDER BY distance;
486
+
```
487
+
488
+
For queries that filter by distance, use a materialized CTE and place the filter outside of it for best performance (due to the[current behavior](https://www.postgresql.org/message-id/flat/CAOdR5yGUoMQ6j7M5hNUXrySzaqZVGf_Ne%2B8fwZMRKTFxU1nbJg%40mail.gmail.com) of the Postgres executor)
489
+
490
+
```sql
491
+
WITH filtered_resultsAS MATERIALIZED (
492
+
SELECT id, embedding<->'[1,2,3]'AS distanceFROM itemsWHERE category_id=123ORDER BY distanceLIMIT5
493
+
)SELECT*FROM filtered_resultsWHERE distance<0.1ORDER BY distance;
494
+
```
495
+
496
+
###Iterative Options
497
+
498
+
Since scanning a large portion of an approximate index is expensive, there are options to control when a scan ends
499
+
500
+
####HNSW
501
+
502
+
Specify the max number of tuples visited (20,000 by default)
503
+
504
+
```sql
505
+
SEThnsw.max_search_tuples=20000;
506
+
```
507
+
508
+
Note: This is approximate and does not apply to the initial scan
509
+
510
+
When increasing this, you may also need to increase the max amount of memory an iterative scan can use, which is a multiple of`work_mem` (2 by default)
511
+
512
+
```sql
513
+
SEThnsw.search_mem_multiplier=4;
514
+
```
515
+
516
+
You can see when this is needed by enabling debug messages
517
+
518
+
```sql
519
+
SET client_min_messages= debug1;
520
+
```
521
+
522
+
which will show when a scan reaches the memory limit
523
+
524
+
```text
525
+
DEBUG: hnsw index scan reached memory limit after 40000 tuples
526
+
HINT: Increase hnsw.search_mem_multiplier to scan more tuples.
527
+
```
528
+
529
+
####IVFFlat
530
+
531
+
Specify the max number of probes
532
+
533
+
```sql
534
+
SETivfflat.max_probes=100;
535
+
```
536
+
537
+
Note: If this is lower than`ivfflat.probes`,`ivfflat.probes` will be used