TODO: can we do better with a different spilling heuristic?
| 552 | |
| 553 | // TODO: can we do better with a different spilling heuristic? |
| 554 | Status PhjBuilder::SpillPartition(BufferedTupleStream::UnpinMode mode, |
| 555 | PhjBuilderPartition** spilled_partition) { |
| 556 | DCHECK_EQ(hash_partitions_.size(), PARTITION_FANOUT); |
| 557 | PhjBuilderPartition* best_candidate = nullptr; |
| 558 | if (null_aware_partition_ != nullptr && null_aware_partition_->CanSpill()) { |
| 559 | // Spill null-aware partition first if possible - it is always processed last. |
| 560 | best_candidate = null_aware_partition_.get(); |
| 561 | } else { |
| 562 | // Iterate over the partitions and pick the largest partition to spill. |
| 563 | int64_t max_freed_mem = 0; |
| 564 | for (const unique_ptr<PhjBuilderPartition>& candidate : hash_partitions_) { |
| 565 | if (!candidate->CanSpill()) continue; |
| 566 | int64_t mem = candidate->build_rows()->BytesPinned(false); |
| 567 | if (candidate->hash_tbl() != nullptr) { |
| 568 | // The hash table should not have matches, since we have not probed it yet. |
| 569 | // Losing match info would lead to incorrect results (IMPALA-1488). |
| 570 | DCHECK(!candidate->hash_tbl()->HasMatches()); |
| 571 | mem += candidate->hash_tbl()->ByteSize(); |
| 572 | } |
| 573 | if (mem > max_freed_mem) { |
| 574 | max_freed_mem = mem; |
| 575 | best_candidate = candidate.get(); |
| 576 | } |
| 577 | } |
| 578 | } |
| 579 | |
| 580 | if (best_candidate == nullptr) { |
| 581 | return Status(Substitute("Internal error: could not find a partition to spill in " |
| 582 | " hash join $0: \n$1\nClient:\n$2", |
| 583 | join_node_id_, DebugString(), buffer_pool_client_->DebugString())); |
| 584 | } |
| 585 | |
| 586 | VLOG(2) << "Spilling partition: " << best_candidate->DebugString() << endl |
| 587 | << DebugString(); |
| 588 | RETURN_IF_ERROR(best_candidate->Spill(mode)); |
| 589 | if (spilled_partition != nullptr) *spilled_partition = best_candidate; |
| 590 | return Status::OK(); |
| 591 | } |
| 592 | |
| 593 | // When this function is called, we've finished processing the current build input |
| 594 | // (either from the child ExecNode or from repartitioning a spilled partition). The build |
nothing calls this directly
no test coverage detected