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