MCPcopy Create free account
hub / github.com/FirebirdSQL/firebird / estimateCost

Method estimateCost

src/jrd/optimizer/InnerJoin.cpp:175–276  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

173//
174
175void InnerJoin::estimateCost(unsigned position,
176 const StreamInfo* stream,
177 double& cost,
178 double& cardinality)
179{
180 fb_assert(joinedStreams[position].number == stream->number);
181
182 const auto sort = (!position && sortPtr) ? *sortPtr : nullptr;
183
184 // Create the optimizer retrieval generation class and calculate
185 // which indexes will be used and the total estimated selectivity will be returned
186 Retrieval retrieval(tdbb, optimizer, stream->number, false, false, sort, true);
187 const auto candidate = retrieval.getInversion();
188 fb_assert(!position || candidate->dependencies);
189
190 // Remember selectivity of this stream
191 joinedStreams[position].selectivity = candidate->selectivity;
192
193 // Get the stream cardinality
194 const auto streamCardinality = csb->csb_rpt[stream->number].csb_cardinality;
195
196 // If the table looks like empty during preparation time, we cannot be sure about
197 // its real cardinality during execution. So, unless we have some index-based
198 // filtering applied, let's better be pessimistic and avoid hash joining due to
199 // likely cardinality under-estimation.
200 const bool avoidHashJoin = (streamCardinality <= MINIMUM_CARDINALITY && !stream->baseIndexes);
201
202 auto currentCardinality = streamCardinality * candidate->selectivity;
203
204 // Given the "first-rows" mode specified (or implied)
205 // and unless an external sort is to be applied afterwards,
206 // fake the expected cardinality to look as low as possible
207 // to estimate the cost just for a single row being produced.
208 // The same rule is used if the retrieval is unique.
209
210 const bool firstRows = (optimizer->favorFirstRows() &&
211 (!sortPtr || !*sortPtr || candidate->navigated));
212
213 if ((candidate->unique || firstRows) && currentCardinality > MINIMUM_CARDINALITY)
214 currentCardinality = MINIMUM_CARDINALITY;
215
216 // Calculate the nested loop cost, it's our default option
217 const auto loopCost = candidate->cost * cardinality;
218 cost = loopCost;
219
220 // Consider whether the current stream can be hash-joined to the prior ones.
221 // Beware conditional retrievals, this is impossible for them.
222
223 if (position && !candidate->condition && !avoidHashJoin)
224 {
225 // Calculate the hashing cost. It consists of the following parts:
226 // - hashed stream retrieval
227 // - copying rows into the hash table (including hash calculation)
228 // - probing the hash table and copying the matched rows
229
230 const auto hashCardinality = stream->baseSelectivity * streamCardinality;
231 const auto hashCost = stream->baseCost +
232 // hashing cost

Callers

nothing calls this directly

Calls 9

getInversionMethod · 0.80
favorFirstRowsMethod · 0.80
checkEquiJoinMethod · 0.80
hasDataMethod · 0.45
containsStreamMethod · 0.45
beginMethod · 0.45
getCountMethod · 0.45
getCapacityMethod · 0.45
addMethod · 0.45

Tested by

no test coverage detected