From: <di...@us...> - 2013-06-30 17:33:06
|
Revision: 58278 http://sourceforge.net/p/firebird/code/58278 Author: dimitr Date: 2013-06-30 17:33:02 +0000 (Sun, 30 Jun 2013) Log Message: ----------- Slightly refactored the optimizer regarding navigational walks. Modified Paths: -------------- firebird/trunk/src/jrd/Optimizer.cpp firebird/trunk/src/jrd/Optimizer.h firebird/trunk/src/jrd/opt.cpp Modified: firebird/trunk/src/jrd/Optimizer.cpp =================================================================== --- firebird/trunk/src/jrd/Optimizer.cpp 2013-06-30 15:20:58 UTC (rev 58277) +++ firebird/trunk/src/jrd/Optimizer.cpp 2013-06-30 17:33:02 UTC (rev 58278) @@ -372,11 +372,12 @@ scratch = NULL; used = false; unique = false; + navigated = false; } OptimizerRetrieval::OptimizerRetrieval(MemoryPool& p, OptimizerBlk* opt, StreamType streamNumber, bool outer, - bool inner, SortNode** sortNode) + bool inner, SortNode* sortNode) : pool(p), alias(p), indexScratches(p), inversionCandidates(p) { /************************************** @@ -400,6 +401,7 @@ this->innerFlag = inner; this->outerFlag = outer; this->sort = sortNode; + this->navigationCandidate = -1; CompilerScratch::csb_repeat* csb_tail = &csb->csb_rpt[this->stream]; relation = csb_tail->csb_relation; @@ -489,7 +491,7 @@ return alias; } -InversionCandidate* OptimizerRetrieval::generateInversion(IndexTableScan** rsb) +InversionCandidate* OptimizerRetrieval::generateInversion() { /************************************** * @@ -542,8 +544,8 @@ getInversionCandidates(&inversions, &indexScratches, 1); - if (sort && rsb) - *rsb = generateNavigation(); + if (sort) + analyzeNavigation(); // Second, handle "OR" comparisons for (OptimizerBlk::opt_conjunct* tail = opt_begin; tail < opt_end; tail++) @@ -639,6 +641,8 @@ } } + invCandidate->navigated = (navigationCandidate >= 0); + #ifdef OPT_DEBUG_RETRIEVAL // Debug printFinalCandidate(invCandidate); @@ -647,35 +651,61 @@ return invCandidate; } -IndexTableScan* OptimizerRetrieval::generateNavigation() +IndexTableScan* OptimizerRetrieval::getNavigation() { /************************************** * - * g e n e r a t e N a v i g a t i o n + * g e t N a v i g a t i o n * ************************************** * * Functional description * **************************************/ + if (navigationCandidate < 0) + return NULL; + + fb_assert(navigationCandidate <= indexScratches.getCount()); + IndexScratch* const indexScratch = &indexScratches[navigationCandidate]; + + // Looks like we can do a navigational walk. Flag that + // we have used this index for navigation, and allocate + // a navigational rsb for it. + indexScratch->idx->idx_runtime_flags |= idx_navigate; + + const USHORT key_length = + ROUNDUP(BTR_key_length(tdbb, relation, indexScratch->idx), sizeof(SLONG)); + + indexScratch->utilized = true; + InversionNode* const index_node = makeIndexScanNode(indexScratch); + + return FB_NEW(*tdbb->getDefaultPool()) + IndexTableScan(csb, getAlias(), stream, index_node, key_length); +} + +void OptimizerRetrieval::analyzeNavigation() +{ +/************************************** + * + * a n a l y z e N a v i g a t i o n + * + ************************************** + * + * Functional description + * + **************************************/ fb_assert(sort); - SortNode* sortPtr = *sort; - if (!sortPtr) - return NULL; - - size_t i = 0; - for (; i < indexScratches.getCount(); ++i) + for (size_t i = 0; i < indexScratches.getCount(); ++i) { + const index_desc* const idx = indexScratches[i].idx; - index_desc* idx = indexScratches[i].idx; - // 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 // sort--note that in the case where the first field is unique, this // could be optimized, since the sort will be performed correctly by // navigating on a unique index on the first field--deej - if (sortPtr->expressions.getCount() > idx->idx_count) + if (sort->expressions.getCount() > idx->idx_count) continue; // if the user-specified access plan for this request didn't @@ -690,7 +720,7 @@ // an expression index if (idx->idx_flags & idx_expressn) { - if (sortPtr->expressions.getCount() != 1) + if (sort->expressions.getCount() != 1) continue; } @@ -698,12 +728,12 @@ // in the exact same order bool usableIndex = true; - index_desc::idx_repeat* idx_tail = idx->idx_rpt; - NestConst<ValueExprNode>* ptr = sortPtr->expressions.begin(); - const bool* descending = sortPtr->descending.begin(); - const int* nullOrder = sortPtr->nullOrder.begin(); + const index_desc::idx_repeat* idx_tail = idx->idx_rpt; + NestConst<ValueExprNode>* ptr = sort->expressions.begin(); + const bool* descending = sort->descending.begin(); + const int* nullOrder = sort->nullOrder.begin(); - for (const NestConst<ValueExprNode>* const end = sortPtr->expressions.end(); + for (const NestConst<ValueExprNode>* const end = sort->expressions.end(); ptr != end; ++ptr, ++descending, ++nullOrder, ++idx_tail) { @@ -757,7 +787,7 @@ // ASF: We currently can't use non-unique index for GROUP BY and DISTINCT with // multi-level and insensitive collation. In NAV, keys are verified with memcmp // but there we don't know length of each level. - if (sortPtr->unique && (tt->getFlags() & TEXTTYPE_SEPARATE_UNIQUE)) + if (sort->unique && (tt->getFlags() & TEXTTYPE_SEPARATE_UNIQUE)) { usableIndex = false; break; @@ -766,64 +796,15 @@ } } - if (!usableIndex) + if (usableIndex) { - // We can't use this index, try next one. - continue; + // Looks like we can do a navigational walk. Remember that. + navigationCandidate = static_cast<int>(i); + return; } - - // Looks like we can do a navigational walk. Flag that - // we have used this index for navigation, and allocate - // a navigational rsb for it. - *sort = NULL; - idx->idx_runtime_flags |= idx_navigate; - - indexScratches[i].utilized = true; - InversionNode* const index_node = makeIndexScanNode(&indexScratches[i]); - const USHORT key_length = ROUNDUP(BTR_key_length(tdbb, relation, idx), sizeof(SLONG)); - return FB_NEW(*tdbb->getDefaultPool()) - IndexTableScan(csb, getAlias(), stream, index_node, key_length); } - - return NULL; } -InversionCandidate* OptimizerRetrieval::getCost() -{ -/************************************** - * - * g e t C o s t - * - ************************************** - * - * Functional description - * - **************************************/ - createIndexScanNodes = false; - setConjunctionsMatched = false; - return generateInversion(NULL); -} - -InversionCandidate* OptimizerRetrieval::getInversion(IndexTableScan** rsb) -{ -/************************************** - * - * g e t I n v e r s i o n - * - ************************************** - * - * Return an inversionCandidate which - * contains a created inversion when an - * index could be used. - * This function should always return - * an InversionCandidate; - * - **************************************/ - createIndexScanNodes = true; - setConjunctionsMatched = true; - return generateInversion(rsb); -} - void OptimizerRetrieval::getInversionCandidates(InversionCandidateList* inversions, IndexScratchList* fromIndexScratches, USHORT scope) const { Modified: firebird/trunk/src/jrd/Optimizer.h =================================================================== --- firebird/trunk/src/jrd/Optimizer.h 2013-06-30 15:20:58 UTC (rev 58277) +++ firebird/trunk/src/jrd/Optimizer.h 2013-06-30 17:33:02 UTC (rev 58278) @@ -147,6 +147,7 @@ IndexScratch* scratch; bool used; bool unique; + bool navigated; Firebird::Array<BoolExprNode*> matches; SortedStreamList dependentFromStreams; @@ -159,18 +160,33 @@ { public: OptimizerRetrieval(MemoryPool& p, OptimizerBlk* opt, StreamType streamNumber, - bool outer, bool inner, SortNode** sortNode); + bool outer, bool inner, SortNode* sortNode); ~OptimizerRetrieval(); - InversionCandidate* getCost(); - InversionCandidate* getInversion(IndexTableScan** rsb); + InversionCandidate* getInversion() + { + createIndexScanNodes = true; + setConjunctionsMatched = true; + return generateInversion(); + } + + InversionCandidate* getCost() + { + createIndexScanNodes = false; + setConjunctionsMatched = false; + + return generateInversion(); + } + + IndexTableScan* getNavigation(); + protected: + void analyzeNavigation(); InversionNode* composeInversion(InversionNode* node1, InversionNode* node2, InversionNode::Type node_type) const; const Firebird::string& getAlias(); - InversionCandidate* generateInversion(IndexTableScan** rsb); - IndexTableScan* generateNavigation(); + InversionCandidate* generateInversion(); void getInversionCandidates(InversionCandidateList* inversions, IndexScratchList* indexScratches, USHORT scope) const; InversionNode* makeIndexNode(const index_desc* idx) const; @@ -198,7 +214,7 @@ public: StreamType stream; Firebird::string alias; - SortNode** sort; + SortNode* sort; jrd_rel* relation; CompilerScratch* csb; Database* database; @@ -209,6 +225,7 @@ bool outerFlag; bool createIndexScanNodes; bool setConjunctionsMatched; + int navigationCandidate; }; class IndexRelationship Modified: firebird/trunk/src/jrd/opt.cpp =================================================================== --- firebird/trunk/src/jrd/opt.cpp 2013-06-30 15:20:58 UTC (rev 58277) +++ firebird/trunk/src/jrd/opt.cpp 2013-06-30 17:33:02 UTC (rev 58278) @@ -2293,10 +2293,10 @@ else { // Persistent table - IndexTableScan* nav_rsb = NULL; OptimizerRetrieval optimizerRetrieval(*tdbb->getDefaultPool(), opt, stream, - outer_flag, inner_flag, sort_ptr); - AutoPtr<InversionCandidate> candidate(optimizerRetrieval.getInversion(&nav_rsb)); + outer_flag, inner_flag, + sort_ptr ? *sort_ptr : NULL); + AutoPtr<InversionCandidate> candidate(optimizerRetrieval.getInversion()); if (candidate) { @@ -2304,12 +2304,15 @@ condition = candidate->condition; } + IndexTableScan* const nav_rsb = optimizerRetrieval.getNavigation(); + if (nav_rsb) { + if (sort_ptr) + *sort_ptr = NULL; + if (inversion && !condition) - { nav_rsb->setInversion(inversion); - } rsb = nav_rsb; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |