| 605 | } |
| 606 | |
| 607 | void doExecuteTask(const DistributedQueryTaskDescription & task_description, ObjectStoragePtr object_storage, |
| 608 | const String & object_storage_path, const String & distributed_query_id, ContextMutablePtr context, |
| 609 | std::function<bool()> is_cancelled, ProgressCallback progress_callback) |
| 610 | { |
| 611 | Stopwatch execute_task_watch; |
| 612 | const auto & task = task_description.task; |
| 613 | |
| 614 | std::shared_ptr<OpenTelemetry::SpanHolder> query_span = std::make_shared<OpenTelemetry::SpanHolder>(task.task_id); |
| 615 | |
| 616 | auto logger = Poco::Logger::getShared("executeDistributedQuery"); |
| 617 | |
| 618 | /// Disable the query condition cache: its per-worker state could make workers read inconsistent |
| 619 | /// data for the same fragment. |
| 620 | context->setSetting("use_query_condition_cache", false); |
| 621 | |
| 622 | Strings input_exchange_streams; |
| 623 | for (const auto & stream_id : task.input_exchange_streams) |
| 624 | input_exchange_streams.push_back(stream_id.toString()); |
| 625 | |
| 626 | Strings output_exchange_streams; |
| 627 | for (const auto & stream_id : task.output_exchange_streams) |
| 628 | output_exchange_streams.push_back(stream_id.toString()); |
| 629 | |
| 630 | LOG_TRACE(logger, "Task '{}' input exchange streams: [{}], output exchange streams: [{}]", |
| 631 | task.task_id, fmt::join(input_exchange_streams, ", "), fmt::join(output_exchange_streams, ", ")); |
| 632 | |
| 633 | #ifdef OS_LINUX |
| 634 | /// Release this task's pending streaming exchange connections on the worker when it ends. A |
| 635 | /// consumer that never connects (e.g. its query was cancelled) would otherwise leave them behind. |
| 636 | /// Only this task's output streams are dropped, so sibling tasks of the same query are unaffected. |
| 637 | SCOPE_EXIT_SAFE(ExchangeConnections::instance()->removePendingStreams(distributed_query_id, output_exchange_streams)); |
| 638 | #endif |
| 639 | |
| 640 | auto temporary_files = createTemporaryFilesLookup( |
| 641 | object_storage, object_storage_path, input_exchange_streams, output_exchange_streams); |
| 642 | |
| 643 | auto pipeline_settings = BuildQueryPipelineSettings(context); |
| 644 | pipeline_settings.temporary_file_lookup = temporary_files; |
| 645 | pipeline_settings.parameter_lookup = std::make_shared<TaskParameters>(task.parameters); |
| 646 | pipeline_settings.exchange_lookup = createExchangeLookup( |
| 647 | distributed_query_id, |
| 648 | task_description.exchanges, |
| 649 | task_description.exchange_stream_sources, |
| 650 | temporary_files, |
| 651 | context); |
| 652 | |
| 653 | auto optimization_settings = QueryPlanOptimizationSettings(context); |
| 654 | |
| 655 | /// Disable stats-driven plan-shape rewrites on the worker side: per-worker |
| 656 | /// stats can diverge and produce incompatible plans across workers (e.g. one |
| 657 | /// swaps the join sides while the others don't), breaking exchange partitioning. |
| 658 | optimization_settings.join_swap_table = std::make_optional(false); |
| 659 | optimization_settings.query_plan_optimize_join_order_limit = 0; |
| 660 | optimization_settings.query_plan_optimize_join_order_randomize = 0; |
| 661 | optimization_settings.convert_join_to_in = false; |
| 662 | optimization_settings.convert_outer_join_to_inner_join = false; |
| 663 | optimization_settings.convert_any_join_to_semi_or_anti_join = false; |
| 664 | optimization_settings.merge_filter_into_join_condition = false; |
no test coverage detected