@@ -28,15 +28,11 @@ use ballista_core::{
28
28
execution_plans:: { ShuffleReaderExec , ShuffleWriterExec , UnresolvedShuffleExec } ,
29
29
serde:: scheduler:: PartitionLocation ,
30
30
} ;
31
- use datafusion:: execution:: context:: { ExecutionConfig , ExecutionContext } ;
32
- use datafusion:: physical_optimizer:: coalesce_batches:: CoalesceBatches ;
33
- use datafusion:: physical_optimizer:: merge_exec:: AddCoalescePartitionsExec ;
34
- use datafusion:: physical_optimizer:: optimizer:: PhysicalOptimizerRule ;
31
+ use datafusion:: execution:: context:: ExecutionContext ;
35
32
use datafusion:: physical_plan:: coalesce_partitions:: CoalescePartitionsExec ;
36
- use datafusion:: physical_plan:: hash_aggregate:: { AggregateMode , HashAggregateExec } ;
37
- use datafusion:: physical_plan:: hash_join:: HashJoinExec ;
33
+ use datafusion:: physical_plan:: repartition:: RepartitionExec ;
38
34
use datafusion:: physical_plan:: windows:: WindowAggExec ;
39
- use datafusion:: physical_plan:: ExecutionPlan ;
35
+ use datafusion:: physical_plan:: { ExecutionPlan , Partitioning } ;
40
36
use log:: info;
41
37
42
38
type PartialQueryStageResult = ( Arc < dyn ExecutionPlan > , Vec < Arc < ShuffleWriterExec > > ) ;
@@ -71,13 +67,18 @@ impl DistributedPlanner {
71
67
info ! ( "planning query stages" ) ;
72
68
let ( new_plan, mut stages) =
73
69
self . plan_query_stages_internal ( job_id, execution_plan) ?;
74
- stages. push ( create_query_stage ( job_id, self . next_stage_id ( ) , new_plan) ?) ;
70
+ stages. push ( create_shuffle_writer (
71
+ job_id,
72
+ self . next_stage_id ( ) ,
73
+ new_plan,
74
+ None ,
75
+ ) ?) ;
75
76
Ok ( stages)
76
77
}
77
78
78
79
/// Returns a potentially modified version of the input execution_plan along with the resulting query stages.
79
80
/// This function is needed because the input execution_plan might need to be modified, but it might not hold a
80
- /// compelte query stage (its parent might also belong to the same stage)
81
+ /// complete query stage (its parent might also belong to the same stage)
81
82
fn plan_query_stages_internal (
82
83
& mut self ,
83
84
job_id : & str ,
@@ -98,58 +99,44 @@ impl DistributedPlanner {
98
99
}
99
100
100
101
if let Some ( adapter) = execution_plan. as_any ( ) . downcast_ref :: < DfTableAdapter > ( ) {
101
- // remove Repartition rule because that isn't supported yet
102
- let rules: Vec < Arc < dyn PhysicalOptimizerRule + Send + Sync > > = vec ! [
103
- Arc :: new( CoalesceBatches :: new( ) ) ,
104
- Arc :: new( AddCoalescePartitionsExec :: new( ) ) ,
105
- ] ;
106
- let config = ExecutionConfig :: new ( ) . with_physical_optimizer_rules ( rules) ;
107
- let ctx = ExecutionContext :: with_config ( config) ;
102
+ let ctx = ExecutionContext :: new ( ) ;
108
103
Ok ( ( ctx. create_physical_plan ( & adapter. logical_plan ) ?, stages) )
109
- } else if let Some ( merge ) = execution_plan
104
+ } else if let Some ( coalesce ) = execution_plan
110
105
. as_any ( )
111
106
. downcast_ref :: < CoalescePartitionsExec > ( )
112
107
{
113
- let query_stage = create_query_stage (
108
+ let query_stage = create_shuffle_writer (
114
109
job_id,
115
110
self . next_stage_id ( ) ,
116
- merge. children ( ) [ 0 ] . clone ( ) ,
111
+ coalesce. children ( ) [ 0 ] . clone ( ) ,
112
+ None ,
117
113
) ?;
118
114
let unresolved_shuffle = Arc :: new ( UnresolvedShuffleExec :: new (
119
115
vec ! [ query_stage. stage_id( ) ] ,
120
116
query_stage. schema ( ) ,
121
117
query_stage. output_partitioning ( ) . partition_count ( ) ,
122
118
) ) ;
123
119
stages. push ( query_stage) ;
124
- Ok ( ( merge. with_new_children ( vec ! [ unresolved_shuffle] ) ?, stages) )
125
- } else if let Some ( agg) =
126
- execution_plan. as_any ( ) . downcast_ref :: < HashAggregateExec > ( )
120
+ Ok ( (
121
+ coalesce. with_new_children ( vec ! [ unresolved_shuffle] ) ?,
122
+ stages,
123
+ ) )
124
+ } else if let Some ( repart) =
125
+ execution_plan. as_any ( ) . downcast_ref :: < RepartitionExec > ( )
127
126
{
128
- //TODO should insert query stages in more generic way based on partitioning metadata
129
- // and not specifically for this operator
130
- match agg. mode ( ) {
131
- AggregateMode :: Final | AggregateMode :: FinalPartitioned => {
132
- let mut new_children: Vec < Arc < dyn ExecutionPlan > > = vec ! [ ] ;
133
- for child in & children {
134
- let new_stage = create_query_stage (
135
- job_id,
136
- self . next_stage_id ( ) ,
137
- child. clone ( ) ,
138
- ) ?;
139
- new_children. push ( Arc :: new ( UnresolvedShuffleExec :: new (
140
- vec ! [ new_stage. stage_id( ) ] ,
141
- new_stage. schema ( ) . clone ( ) ,
142
- new_stage. output_partitioning ( ) . partition_count ( ) ,
143
- ) ) ) ;
144
- stages. push ( new_stage) ;
145
- }
146
- Ok ( ( agg. with_new_children ( new_children) ?, stages) )
147
- }
148
- AggregateMode :: Partial => Ok ( ( agg. with_new_children ( children) ?, stages) ) ,
149
- }
150
- } else if let Some ( join) = execution_plan. as_any ( ) . downcast_ref :: < HashJoinExec > ( )
151
- {
152
- Ok ( ( join. with_new_children ( children) ?, stages) )
127
+ let query_stage = create_shuffle_writer (
128
+ job_id,
129
+ self . next_stage_id ( ) ,
130
+ repart. children ( ) [ 0 ] . clone ( ) ,
131
+ Some ( repart. partitioning ( ) . to_owned ( ) ) ,
132
+ ) ?;
133
+ let unresolved_shuffle = Arc :: new ( UnresolvedShuffleExec :: new (
134
+ vec ! [ query_stage. stage_id( ) ] ,
135
+ query_stage. schema ( ) ,
136
+ query_stage. output_partitioning ( ) . partition_count ( ) ,
137
+ ) ) ;
138
+ stages. push ( query_stage) ;
139
+ Ok ( ( unresolved_shuffle, stages) )
153
140
} else if let Some ( window) =
154
141
execution_plan. as_any ( ) . downcast_ref :: < WindowAggExec > ( )
155
142
{
@@ -158,25 +145,7 @@ impl DistributedPlanner {
158
145
window
159
146
) ) )
160
147
} else {
161
- // TODO check for compatible partitioning schema, not just count
162
- if execution_plan. output_partitioning ( ) . partition_count ( )
163
- != children[ 0 ] . output_partitioning ( ) . partition_count ( )
164
- {
165
- let mut new_children: Vec < Arc < dyn ExecutionPlan > > = vec ! [ ] ;
166
- for child in & children {
167
- let new_stage =
168
- create_query_stage ( job_id, self . next_stage_id ( ) , child. clone ( ) ) ?;
169
- new_children. push ( Arc :: new ( UnresolvedShuffleExec :: new (
170
- vec ! [ new_stage. stage_id( ) ] ,
171
- new_stage. schema ( ) . clone ( ) ,
172
- new_stage. output_partitioning ( ) . partition_count ( ) ,
173
- ) ) ) ;
174
- stages. push ( new_stage) ;
175
- }
176
- Ok ( ( execution_plan. with_new_children ( new_children) ?, stages) )
177
- } else {
178
- Ok ( ( execution_plan. with_new_children ( children) ?, stages) )
179
- }
148
+ Ok ( ( execution_plan. with_new_children ( children) ?, stages) )
180
149
}
181
150
}
182
151
@@ -224,17 +193,18 @@ pub fn remove_unresolved_shuffles(
224
193
Ok ( stage. with_new_children ( new_children) ?)
225
194
}
226
195
227
- fn create_query_stage (
196
+ fn create_shuffle_writer (
228
197
job_id : & str ,
229
198
stage_id : usize ,
230
199
plan : Arc < dyn ExecutionPlan > ,
200
+ partitioning : Option < Partitioning > ,
231
201
) -> Result < Arc < ShuffleWriterExec > > {
232
202
Ok ( Arc :: new ( ShuffleWriterExec :: try_new (
233
203
job_id. to_owned ( ) ,
234
204
stage_id,
235
205
plan,
236
206
"" . to_owned ( ) , // executor will decide on the work_dir path
237
- None ,
207
+ partitioning ,
238
208
) ?) )
239
209
}
240
210
0 commit comments