@@ -43,6 +43,7 @@ use datafusion::sql::parser::DFParser;
4343use datafusion:: sql:: resolve:: resolve_table_references;
4444use datafusion:: sql:: sqlparser:: dialect:: PostgreSqlDialect ;
4545use futures:: Stream ;
46+ use futures:: StreamExt ;
4647use itertools:: Itertools ;
4748use once_cell:: sync:: Lazy ;
4849use serde:: { Deserialize , Serialize } ;
@@ -54,7 +55,7 @@ use std::sync::{Arc, RwLock};
5455use std:: task:: { Context , Poll } ;
5556use sysinfo:: System ;
5657use tokio:: runtime:: Runtime ;
57- use tokio_stream:: wrappers:: ReceiverStream ;
58+ use tokio_stream:: wrappers:: UnboundedReceiverStream ;
5859use tracing:: Instrument ;
5960
6061use self :: error:: ExecuteError ;
@@ -217,7 +218,8 @@ impl Query {
217218 . with_prefer_existing_sort ( true )
218219 //batch size has been made configurable via environment variable
219220 //default value is 20000
220- . with_batch_size ( PARSEABLE . options . execution_batch_size ) ;
221+ . with_batch_size ( PARSEABLE . options . execution_batch_size )
222+ . with_target_partitions ( PARSEABLE . options . target_partitions as usize ) ;
221223
222224 // Pushdown filters allows DF to push the filters as far down in the plan as possible
223225 // and thus, reducing the number of rows decoded
@@ -226,10 +228,22 @@ impl Query {
226228 // Reorder filters allows DF to decide the order of filters minimizing the cost of filter evaluation
227229 config. options_mut ( ) . execution . parquet . reorder_filters = true ;
228230 config. options_mut ( ) . execution . parquet . binary_as_string = true ;
231+ // Bump footer-read hint from the 512 KiB default. Streams with
232+ // many label columns + page-indexed value columns can have
233+ // parquet footers in the 1-2 MiB range; sizing the hint above
234+ // the actual footer collapses the two-read fallback into a
235+ // single GET per file, saving a round trip on every file open.
236+ config. options_mut ( ) . execution . parquet . metadata_size_hint = Some ( 2 * 1024 * 1024 ) ;
229237 config
230238 . options_mut ( )
231239 . execution
232240 . use_row_number_estimates_to_optimize_partitioning = true ;
241+ config. options_mut ( ) . execution . parquet . enable_page_index = true ;
242+ config
243+ . options_mut ( )
244+ . execution
245+ . parquet
246+ . max_predicate_cache_size = Some ( 1024 * 1024 * 1024 ) ;
233247
234248 //adding this config as it improves query performance as explained here -
235249 // https://github.com/apache/datafusion/pull/13101
@@ -308,23 +322,21 @@ impl Query {
308322 } ) ;
309323
310324 let partition_streams = execute_stream_partitioned ( plan. clone ( ) , task_ctx. clone ( ) ) ?;
311- let n = partition_streams. len ( ) ;
312- // Bound channel so a slow consumer backpressures producers — caps peak memory.
313- let ( tx, rx) = tokio:: sync:: mpsc:: channel :: <
325+
326+ let ( tx, rx) = tokio:: sync:: mpsc:: unbounded_channel :: <
314327 Result < RecordBatch , datafusion:: error:: DataFusionError > ,
315- > ( ( num_cpus :: get ( ) * 4 ) . max ( n * 2 ) . max ( 1 ) ) ;
328+ > ( ) ;
316329
317- for s in partition_streams {
330+ for s in partition_streams. into_iter ( ) {
318331 let wrapped =
319332 PartitionedMetricMonitor :: new ( s, monitor_state. clone ( ) , tenant_id. clone ( ) ) ;
320333 let tx = tx. clone ( ) ;
321334 let span = tracing:: Span :: current ( ) ;
322335 tokio:: spawn (
323336 async move {
324337 let mut stream: SendableRecordBatchStream = Box :: pin ( wrapped) ;
325- use futures:: StreamExt ;
326338 while let Some ( batch) = stream. next ( ) . await {
327- if tx. send ( batch) . await . is_err ( ) {
339+ if tx. send ( batch) . is_err ( ) {
328340 break ;
329341 }
330342 }
@@ -334,7 +346,7 @@ impl Query {
334346 }
335347 drop ( tx) ;
336348
337- let merged = ReceiverStream :: new ( rx) ;
349+ let merged = UnboundedReceiverStream :: new ( rx) ;
338350 let final_stream = RecordBatchStreamAdapter :: new ( plan. schema ( ) , merged) ;
339351 Either :: Right ( Box :: pin ( final_stream) as SendableRecordBatchStream )
340352 } ;
0 commit comments