Skip to content

Commit 81d6d22

Browse files
committed
Allow position cardinality < 1, it's valid when multiple conjuncts are used (and it provides better cost estimations)
1 parent e8de18c commit 81d6d22

4 files changed

Lines changed: 16 additions & 28 deletions

File tree

src/jrd/optimizer/InnerJoin.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,14 @@ void InnerJoin::estimateCost(unsigned position,
189189
// Remember selectivity of this stream
190190
joinedStreams[position].selectivity = candidate->selectivity;
191191

192+
// Calculate the nested loop cost, it's our default option
193+
const auto loopCost = candidate->cost * cardinality;
194+
cost = loopCost;
195+
192196
// Get the stream cardinality
193197
const auto streamCardinality = csb->csb_rpt[stream->number].csb_cardinality;
194198

195-
// If the table looks like empty during preparation time, we cannot be sure about
196-
// its real cardinality during execution. So, unless we have some index-based
197-
// filtering applied, let's better be pessimistic and avoid hash joining due to
198-
// likely cardinality under-estimation.
199-
const bool avoidHashJoin = (streamCardinality <= MINIMUM_CARDINALITY && !stream->baseIndexes);
200-
199+
// Calculate the retrieval cardinality
201200
auto currentCardinality = streamCardinality * candidate->selectivity;
202201

203202
// Given the "first-rows" mode specified (or implied)
@@ -212,9 +211,11 @@ void InnerJoin::estimateCost(unsigned position,
212211
if ((candidate->unique || firstRows) && currentCardinality > MINIMUM_CARDINALITY)
213212
currentCardinality = MINIMUM_CARDINALITY;
214213

215-
// Calculate the nested loop cost, it's our default option
216-
const auto loopCost = candidate->cost * cardinality;
217-
cost = loopCost;
214+
// If the table looks like empty during preparation time, we cannot be sure about
215+
// its real cardinality during execution. So, unless we have some index-based
216+
// filtering applied, let's better be pessimistic and avoid hash joining due to
217+
// likely cardinality under-estimation.
218+
const bool avoidHashJoin = (streamCardinality <= MINIMUM_CARDINALITY && !stream->baseIndexes);
218219

219220
// Consider whether the current stream can be hash-joined to the prior ones.
220221
// Beware conditional retrievals, this is impossible for them.
@@ -271,7 +272,7 @@ void InnerJoin::estimateCost(unsigned position,
271272
}
272273
}
273274

274-
cardinality = MAX(currentCardinality, MINIMUM_CARDINALITY);
275+
cardinality = currentCardinality;
275276
}
276277

277278

src/jrd/optimizer/Optimizer.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,15 +434,9 @@ class Optimizer final : public Firebird::PermanentStorage
434434
return MIN(selectivity, MAXIMUM_SELECTIVITY / 2);
435435
}
436436

437-
static void adjustSelectivity(double& selectivity, double factor, double cardinality) noexcept
437+
static void adjustSelectivity(double& selectivity, double factor) noexcept
438438
{
439-
if (!cardinality)
440-
cardinality = DEFAULT_CARDINALITY;
441-
442-
const auto minSelectivity = MAXIMUM_SELECTIVITY / cardinality;
443-
const auto diffSelectivity = selectivity > minSelectivity ?
444-
selectivity - minSelectivity : 0;
445-
selectivity = minSelectivity + diffSelectivity * factor;
439+
selectivity = MIN(selectivity * factor, MAXIMUM_SELECTIVITY);
446440
}
447441

448442
bool deliverJoinConjuncts(const BoolExprNodeStack& conjuncts) const

src/jrd/optimizer/Retrieval.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ InversionCandidate* Retrieval::getInversion()
355355
}
356356
}
357357

358-
Optimizer::adjustSelectivity(invCandidate->selectivity, selectivity, cardinality);
358+
Optimizer::adjustSelectivity(invCandidate->selectivity, selectivity);
359359

360360
// Add the streams where this stream is depending on
361361
for (auto match : invCandidate->matches)
@@ -419,7 +419,7 @@ IndexTableScan* Retrieval::getNavigation(const InversionCandidate* candidate)
419419
}
420420
}
421421

422-
Optimizer::adjustSelectivity(selectivity, factor, streamCardinality);
422+
Optimizer::adjustSelectivity(selectivity, factor);
423423

424424
// Don't consider external sorting if optimization for first rows is requested
425425
// and we have no local filtering applied

src/jrd/recsrc/FilteredStream.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,7 @@ FilteredStream::FilteredStream(CompilerScratch* csb, RecordSource* next,
4646
fb_assert(m_next && m_boolean);
4747

4848
m_impure = csb->allocImpure<Impure>();
49-
50-
auto cardinality = next->getCardinality();
51-
if (selectivity)
52-
{
53-
Optimizer::adjustSelectivity(selectivity, MAXIMUM_SELECTIVITY, cardinality);
54-
cardinality *= selectivity;
55-
}
56-
m_cardinality = cardinality;
49+
m_cardinality = next->getCardinality() * selectivity;
5750
}
5851

5952
FilteredStream::FilteredStream(CompilerScratch* csb, RecordSource* next,

0 commit comments

Comments
 (0)