@@ -44,6 +44,7 @@ use datafusion::sql::parser::DFParser;
4444use datafusion:: sql:: resolve:: resolve_table_references;
4545use datafusion:: sql:: sqlparser:: dialect:: PostgreSqlDialect ;
4646use futures:: Stream ;
47+ use futures:: StreamExt ;
4748use itertools:: Itertools ;
4849use once_cell:: sync:: { Lazy , OnceCell } ;
4950use serde:: { Deserialize , Serialize } ;
@@ -55,7 +56,7 @@ use std::sync::{Arc, RwLock};
5556use std:: task:: { Context , Poll } ;
5657use sysinfo:: System ;
5758use tokio:: runtime:: Runtime ;
58- use tokio_stream:: wrappers:: ReceiverStream ;
59+ use tokio_stream:: wrappers:: UnboundedReceiverStream ;
5960use tracing:: Instrument ;
6061
6162use self :: error:: ExecuteError ;
@@ -251,7 +252,8 @@ impl Query {
251252 . with_prefer_existing_sort ( true )
252253 //batch size has been made configurable via environment variable
253254 //default value is 20000
254- . with_batch_size ( PARSEABLE . options . execution_batch_size ) ;
255+ . with_batch_size ( PARSEABLE . options . execution_batch_size )
256+ . with_target_partitions ( PARSEABLE . options . target_partitions as usize ) ;
255257
256258 // Pushdown filters allows DF to push the filters as far down in the plan as possible
257259 // and thus, reducing the number of rows decoded
@@ -260,10 +262,22 @@ impl Query {
260262 // Reorder filters allows DF to decide the order of filters minimizing the cost of filter evaluation
261263 config. options_mut ( ) . execution . parquet . reorder_filters = true ;
262264 config. options_mut ( ) . execution . parquet . binary_as_string = true ;
265+ // Bump footer-read hint from the 512 KiB default. Streams with
266+ // many label columns + page-indexed value columns can have
267+ // parquet footers in the 1-2 MiB range; sizing the hint above
268+ // the actual footer collapses the two-read fallback into a
269+ // single GET per file, saving a round trip on every file open.
270+ config. options_mut ( ) . execution . parquet . metadata_size_hint = Some ( 2 * 1024 * 1024 ) ;
263271 config
264272 . options_mut ( )
265273 . execution
266274 . use_row_number_estimates_to_optimize_partitioning = true ;
275+ config. options_mut ( ) . execution . parquet . enable_page_index = true ;
276+ config
277+ . options_mut ( )
278+ . execution
279+ . parquet
280+ . max_predicate_cache_size = Some ( 1024 * 1024 * 1024 ) ;
267281
268282 //adding this config as it improves query performance as explained here -
269283 // https://github.com/apache/datafusion/pull/13101
@@ -348,23 +362,21 @@ impl Query {
348362 } ) ;
349363
350364 let partition_streams = execute_stream_partitioned ( plan. clone ( ) , task_ctx. clone ( ) ) ?;
351- let n = partition_streams. len ( ) ;
352- // Bound channel so a slow consumer backpressures producers — caps peak memory.
353- let ( tx, rx) = tokio:: sync:: mpsc:: channel :: <
365+
366+ let ( tx, rx) = tokio:: sync:: mpsc:: unbounded_channel :: <
354367 Result < RecordBatch , datafusion:: error:: DataFusionError > ,
355- > ( ( num_cpus :: get ( ) * 4 ) . max ( n * 2 ) . max ( 1 ) ) ;
368+ > ( ) ;
356369
357- for s in partition_streams {
370+ for s in partition_streams. into_iter ( ) {
358371 let wrapped =
359372 PartitionedMetricMonitor :: new ( s, monitor_state. clone ( ) , tenant_id. clone ( ) ) ;
360373 let tx = tx. clone ( ) ;
361374 let span = tracing:: Span :: current ( ) ;
362375 tokio:: spawn (
363376 async move {
364377 let mut stream: SendableRecordBatchStream = Box :: pin ( wrapped) ;
365- use futures:: StreamExt ;
366378 while let Some ( batch) = stream. next ( ) . await {
367- if tx. send ( batch) . await . is_err ( ) {
379+ if tx. send ( batch) . is_err ( ) {
368380 break ;
369381 }
370382 }
@@ -374,7 +386,7 @@ impl Query {
374386 }
375387 drop ( tx) ;
376388
377- let merged = ReceiverStream :: new ( rx) ;
389+ let merged = UnboundedReceiverStream :: new ( rx) ;
378390 let final_stream = RecordBatchStreamAdapter :: new ( plan. schema ( ) , merged) ;
379391 Either :: Right ( Box :: pin ( final_stream) as SendableRecordBatchStream )
380392 } ;
0 commit comments