| 1578 | |
| 1579 | template <bool ignoreNullKeys> |
| 1580 | void HashTable<ignoreNullKeys>::decideHashMode( |
| 1581 | int32_t numNew, |
| 1582 | bool disableRangeArrayHash) { |
| 1583 | std::vector<uint64_t> rangeSizes(hashers_.size()); |
| 1584 | std::vector<uint64_t> distinctSizes(hashers_.size()); |
| 1585 | std::vector<bool> useRange(hashers_.size()); |
| 1586 | uint64_t bestWithReserve = 1; |
| 1587 | uint64_t distinctsWithReserve = 1; |
| 1588 | uint64_t rangesWithReserve = 1; |
| 1589 | // Permanently turn off kArray hash mode with key value ranges after this is |
| 1590 | // first requested. |
| 1591 | if (disableRangeArrayHash && numNew == 0 && disableRangeArrayHash_) { |
| 1592 | // The option is already set and no new rows are added. Return. |
| 1593 | return; |
| 1594 | } |
| 1595 | disableRangeArrayHash_ |= disableRangeArrayHash; |
| 1596 | if (numDistinct_ && (!isJoinBuild_ || joinBuildNoDuplicates_)) { |
| 1597 | // If the join type is left semi and anti, allowDuplicates_ will be false, |
| 1598 | // and join build is building hash table while adding input rows. |
| 1599 | if (!analyze()) { |
| 1600 | setHashMode(HashMode::kHash, numNew); |
| 1601 | return; |
| 1602 | } |
| 1603 | } |
| 1604 | for (int i = 0; i < hashers_.size(); ++i) { |
| 1605 | hashers_[i]->cardinality(reservePct(), rangeSizes[i], distinctSizes[i]); |
| 1606 | distinctsWithReserve = safeMul(distinctsWithReserve, distinctSizes[i]); |
| 1607 | rangesWithReserve = safeMul(rangesWithReserve, rangeSizes[i]); |
| 1608 | if (distinctSizes[i] == VectorHasher::kRangeTooLarge && |
| 1609 | rangeSizes[i] != VectorHasher::kRangeTooLarge) { |
| 1610 | useRange[i] = true; |
| 1611 | bestWithReserve = safeMul(bestWithReserve, rangeSizes[i]); |
| 1612 | } else if ( |
| 1613 | rangeSizes[i] != VectorHasher::kRangeTooLarge && |
| 1614 | rangeSizes[i] <= distinctSizes[i] * 20) { |
| 1615 | useRange[i] = true; |
| 1616 | bestWithReserve = safeMul(bestWithReserve, rangeSizes[i]); |
| 1617 | } else { |
| 1618 | bestWithReserve = safeMul(bestWithReserve, distinctSizes[i]); |
| 1619 | } |
| 1620 | } |
| 1621 | |
| 1622 | if (rangesWithReserve < kArrayHashMaxSize && !disableRangeArrayHash_) { |
| 1623 | std::fill(useRange.begin(), useRange.end(), true); |
| 1624 | capacity_ = setHasherMode(hashers_, useRange, rangeSizes, distinctSizes); |
| 1625 | setHashMode(HashMode::kArray, numNew); |
| 1626 | return; |
| 1627 | } |
| 1628 | |
| 1629 | if (bestWithReserve < kArrayHashMaxSize || |
| 1630 | (disableRangeArrayHash_ && bestWithReserve < numDistinct_ * 2)) { |
| 1631 | capacity_ = setHasherMode(hashers_, useRange, rangeSizes, distinctSizes); |
| 1632 | setHashMode(HashMode::kArray, numNew); |
| 1633 | return; |
| 1634 | } |
| 1635 | if (rangesWithReserve != VectorHasher::kRangeTooLarge) { |
| 1636 | std::fill(useRange.begin(), useRange.end(), true); |
| 1637 | setHasherMode(hashers_, useRange, rangeSizes, distinctSizes); |