8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 14:03:07 +01:00

Correction for CORE-1550: Unnecessary index scan happens when the same index is mapped to both WHERE and ORDER BY clauses.

Also resolved CORE-1846: Allow index walk (ORDER plan) when there's a composite index {A, B} and the query looks like WHERE A = ? ORDER BY B.
This commit is contained in:
dimitr 2013-11-28 17:26:54 +00:00
parent 6b22039d4f
commit a5cde2bbb4

View File

@ -674,6 +674,7 @@ void OptimizerRetrieval::analyzeNavigation()
{
IndexScratch* const indexScratch = &indexScratches[i];
const index_desc* const idx = indexScratch->idx;
const int equalSegments = MIN(indexScratch->lowerCount, indexScratch->upperCount);
// if the number of fields in the sort is greater than the number of
// fields in the index, the index will not be used to optimize the
@ -704,6 +705,7 @@ void OptimizerRetrieval::analyzeNavigation()
bool usableIndex = true;
const index_desc::idx_repeat* idx_tail = idx->idx_rpt;
const index_desc::idx_repeat* const idx_end = idx_tail + idx->idx_count;
NestConst<ValueExprNode>* ptr = sort->expressions.begin();
const bool* descending = sort->descending.begin();
const int* nullOrder = sort->nullOrder.begin();
@ -723,13 +725,27 @@ void OptimizerRetrieval::analyzeNavigation()
break;
}
}
else if (!(fieldNode = node->as<FieldNode>()) ||
fieldNode->fieldStream != stream ||
fieldNode->fieldId != idx_tail->idx_field)
else if (!(fieldNode = node->as<FieldNode>()) || fieldNode->fieldStream != stream)
{
usableIndex = false;
break;
}
else
{
for (; idx_tail < idx_end && fieldNode->fieldId != idx_tail->idx_field; idx_tail++)
{
const int segmentNumber = idx_tail - idx->idx_rpt;
if (segmentNumber >= equalSegments)
break;
}
if (idx_tail >= idx_end || fieldNode->fieldId != idx_tail->idx_field)
{
usableIndex = false;
break;
}
}
if ((*descending && !(idx->idx_flags & idx_descending)) ||
(!*descending && (idx->idx_flags & idx_descending)) ||
@ -1273,7 +1289,12 @@ InversionCandidate* OptimizerRetrieval::makeInversion(InversionCandidateList* in
for (i = 0; i < navigationCandidate->segments.getCount(); i++)
{
const IndexScratchSegment* const segment = navigationCandidate->segments[i];
matches.join(segment->matches);
for (size_t j = 0; j < segment->matches.getCount(); j++)
{
if (!matches.exist(segment->matches[j]))
matches.add(segment->matches[j]);
}
}
}
@ -1346,9 +1367,8 @@ InversionCandidate* OptimizerRetrieval::makeInversion(InversionCandidateList* in
// index, add also the other matches from this index.
for (size_t j = 0; j < currentInv->matches.getCount(); j++)
{
if (!matches.exist(currentInv->matches[j])) {
if (!matches.exist(currentInv->matches[j]))
matches.add(currentInv->matches[j]);
}
}
// Restart loop, because other indexes could also be excluded now.
restartLoop = true;
@ -1538,15 +1558,13 @@ InversionCandidate* OptimizerRetrieval::makeInversion(InversionCandidateList* in
for (size_t j = 0; j < bestCandidate->matches.getCount(); j++)
{
if (!matches.exist(bestCandidate->matches[j])) {
if (!matches.exist(bestCandidate->matches[j]))
matches.add(bestCandidate->matches[j]);
}
}
if (bestCandidate->boolean)
{
if (!matches.exist(bestCandidate->boolean)) {
if (!matches.exist(bestCandidate->boolean))
matches.add(bestCandidate->boolean);
}
}
}
else
@ -1604,9 +1622,8 @@ InversionCandidate* OptimizerRetrieval::makeInversion(InversionCandidateList* in
}
}
if (invCandidate && matches.getCount()) {
if (invCandidate && matches.getCount())
invCandidate->matches.join(matches);
}
return invCandidate;
}