| 348 | } |
| 349 | |
| 350 | ExecutePlan TableScanExecutor::buildExecutePlan(const DistributedPipelineSettings & distributed_settings) |
| 351 | { |
| 352 | if (!match_projection) |
| 353 | return {}; |
| 354 | |
| 355 | PartGroups part_groups; |
| 356 | { |
| 357 | auto parts = storage.getDataPartsVector(); |
| 358 | if (distributed_settings.source_task_index && distributed_settings.source_task_count) |
| 359 | { |
| 360 | auto size_before_filtering = parts.size(); |
| 361 | filterParts(parts, distributed_settings.source_task_index.value(), distributed_settings.source_task_count.value()); |
| 362 | LOG_TRACE( |
| 363 | log, |
| 364 | "After filtering(index:{}, count:{}) the number of parts of table {} becomes {} from {}", |
| 365 | distributed_settings.source_task_index.value(), |
| 366 | distributed_settings.source_task_count.value(), |
| 367 | storage.getTableName(), |
| 368 | parts.size(), |
| 369 | size_before_filtering); |
| 370 | } |
| 371 | parts.erase(std::remove_if(parts.begin(), parts.end(), [](auto & part) { return part->info.isFakeDropRangePart(); }), parts.end()); |
| 372 | |
| 373 | LOG_DEBUG(log, "Num of parts before part pruning: {}", std::to_string(parts.size())); |
| 374 | |
| 375 | prunePartsByIndex(parts); |
| 376 | |
| 377 | LOG_DEBUG(log, "Num of parts after part pruning: {}", std::to_string(parts.size())); |
| 378 | |
| 379 | if (parts.size() > 100000) |
| 380 | throw Exception(ErrorCodes::PROJECTION_SELECTION_ERROR, "Projection selection error: too many parts before part grouping"); |
| 381 | |
| 382 | part_groups = groupPartsBySchema(parts); |
| 383 | |
| 384 | LOG_DEBUG(log, "Num of part groups before part grouping: {}", std::to_string(part_groups.size())); |
| 385 | |
| 386 | if (part_groups.size() > 100) |
| 387 | throw Exception(ErrorCodes::PROJECTION_SELECTION_ERROR, "Projection selection error: Too many part groups before projection selection"); |
| 388 | } |
| 389 | |
| 390 | ExecutePlan execute_plan; |
| 391 | auto table_columns = storage_metadata->getColumns().getAllPhysical(); |
| 392 | |
| 393 | for (auto & part_group: part_groups) |
| 394 | { |
| 395 | ProjectionMatchContexts projection_candidates; |
| 396 | |
| 397 | // collect qualified projection candidate |
| 398 | for (const auto & projection_desc: storage_metadata->projections) |
| 399 | if (part_group.hasProjection(projection_desc.name)) |
| 400 | { |
| 401 | projection_candidates.emplace_back(projection_desc, part_group, &storage, table_columns); |
| 402 | if (!match(projection_candidates.back())) |
| 403 | projection_candidates.pop_back(); |
| 404 | } |
| 405 | |
| 406 | // select best projection by marks to read |
| 407 | ProjectionMatchContext * selected_candidate = nullptr; |
no test coverage detected