77
88from engine .base_client .distances import Distance
99from engine .base_client .search import BaseSearcher
10- from engine .clients .pgvector .config import get_db_config
10+ from engine .clients .pgvector .config import (
11+ get_db_config ,
12+ PGVECTOR_MAX_PARALLEL_WORKERS_PER_GATHER ,
13+ PGVECTOR_PARALLEL_TUPLE_COST ,
14+ PGVECTOR_PARALLEL_SETUP_COST ,
15+ PGVECTOR_MIN_PARALLEL_TABLE_SCAN_SIZE ,
16+ PGVECTOR_FORCE_PARALLEL_MODE ,
17+ PGVECTOR_WORK_MEM ,
18+ )
1119from engine .clients .pgvector .parser import PgVectorConditionParser
1220
1321
@@ -26,10 +34,28 @@ def init_client(cls, host, distance, connection_params: dict, search_params: dic
2634 cls .distance = distance
2735 cls .search_params = search_params ["search_params" ]
2836
29- # For FLAT searches, disable index usage to force full scan
37+ # For FLAT searches, optimize for parallel execution
3038 if "force_flat" in cls .search_params and cls .search_params ["force_flat" ]:
31- cls .cur .execute ("SET enable_indexscan = off" )
32- cls .cur .execute ("SET enable_bitmapscan = off" )
39+ # Note: We don't disable indexes globally since:
40+ # 1. No vector index exists in FLAT mode (not created)
41+ # 2. PostgreSQL will naturally do sequential scan for vector queries
42+ # 3. Other indexes (for filtering, etc.) remain useful
43+
44+ # Configurable parallel execution settings for FLAT searches
45+ # Priority: Environment variables (from config) > search_params > defaults
46+ parallel_workers = cls .search_params .get ("max_parallel_workers_per_gather" , PGVECTOR_MAX_PARALLEL_WORKERS_PER_GATHER )
47+ parallel_tuple_cost = cls .search_params .get ("parallel_tuple_cost" , PGVECTOR_PARALLEL_TUPLE_COST )
48+ parallel_setup_cost = cls .search_params .get ("parallel_setup_cost" , PGVECTOR_PARALLEL_SETUP_COST )
49+ min_parallel_size = cls .search_params .get ("min_parallel_table_scan_size" , PGVECTOR_MIN_PARALLEL_TABLE_SCAN_SIZE )
50+ force_parallel = cls .search_params .get ("force_parallel_mode" , PGVECTOR_FORCE_PARALLEL_MODE )
51+ work_mem = cls .search_params .get ("work_mem" , PGVECTOR_WORK_MEM )
52+
53+ cls .cur .execute (f"SET max_parallel_workers_per_gather = { parallel_workers } " )
54+ cls .cur .execute (f"SET parallel_tuple_cost = { parallel_tuple_cost } " )
55+ cls .cur .execute (f"SET parallel_setup_cost = { parallel_setup_cost } " )
56+ cls .cur .execute (f"SET min_parallel_table_scan_size = '{ min_parallel_size } '" )
57+ cls .cur .execute (f"SET force_parallel_mode = { force_parallel } " )
58+ cls .cur .execute (f"SET work_mem = '{ work_mem } '" )
3359
3460 @classmethod
3561 def search_one (cls , vector , meta_conditions , top ) -> List [Tuple [int , float ]]:
@@ -73,12 +99,5 @@ def search_one(cls, vector, meta_conditions, top) -> List[Tuple[int, float]]:
7399 @classmethod
74100 def delete_client (cls ):
75101 if cls .cur :
76- # Reset index settings if they were disabled for FLAT searches
77- if "force_flat" in cls .search_params and cls .search_params ["force_flat" ]:
78- try :
79- cls .cur .execute ("SET enable_indexscan = on" )
80- cls .cur .execute ("SET enable_bitmapscan = on" )
81- except :
82- pass # Connection might be closed already
83102 cls .cur .close ()
84103 cls .conn .close ()
0 commit comments