|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.eigenbase.relopt.RelOptRule com.lucidera.opt.LoptOptimizeJoinRule
public class LoptOptimizeJoinRule
LoptOptimizeJoinRule implements the heuristic planner for determining optimal join orderings. It is triggered by the pattern ProjectRel(MultiJoinRel).
Field Summary | |
---|---|
static LoptOptimizeJoinRule |
instance
|
Fields inherited from class org.eigenbase.relopt.RelOptRule |
---|
ANY, description, operands |
Constructor Summary | |
---|---|
private |
LoptOptimizeJoinRule()
Creates a LoptOptimizeJoinRule. |
Method Summary | |
---|---|
private RelNode |
addAdditionalFilters(RelNode joinTree,
LoptMultiJoin multiJoin,
LoptJoinTree left,
LoptJoinTree right,
List<RexNode> filtersToAdd)
Determines whether any additional filters are applicable to a jointree. |
private LoptJoinTree |
addFactorToTree(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
LoptJoinTree joinTree,
int factorToAdd,
BitSet factorsNeeded,
List<RexNode> filtersToAdd,
boolean selfJoin)
Adds a new factor into the current join tree. |
private RexNode |
addFilters(LoptMultiJoin multiJoin,
LoptJoinTree leftTree,
int leftIdx,
LoptJoinTree rightTree,
List<RexNode> filtersToAdd,
boolean adjust)
Determines which join filters can be added to the current join tree. |
private LoptJoinTree |
addToTop(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
LoptJoinTree joinTree,
int factorToAdd,
List<RexNode> filtersToAdd,
boolean selfJoin)
Creates a join tree with the new factor added to the top of the tree |
private RexNode |
adjustFilter(LoptMultiJoin multiJoin,
LoptJoinTree left,
LoptJoinTree right,
RexNode condition,
int factorAdded,
List<Integer> origJoinOrder,
RelDataTypeField[] origFields)
Adjusts a filter to reflect a newly added factor in the middle of an existing join tree |
private static boolean |
areSelfJoinKeysUnique(RelNode leftRel,
RelNode rightRel,
RexNode joinFilters)
Determines if the equality portion of a self-join condition is between identical keys that are unique. |
private Double |
computeJoinCardinality(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
LoptJoinTree joinTree,
List<RexNode> filters,
int factor)
Computes the cardinality of the join columns from a particular factor, when that factor is joined with another join tree. |
private LoptJoinTree |
createJoinSubtree(LoptMultiJoin multiJoin,
LoptJoinTree left,
LoptJoinTree right,
RexNode condition,
JoinRelType joinType,
List<RexNode> filtersToAdd,
boolean fullAdjust,
boolean selfJoin)
Creates a JoinRel given left and right operands and a join condition. |
private LoptJoinTree |
createOrdering(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
int firstFactor)
Generates a join tree with a specific factor as the first factor in the join tree |
private LoptJoinTree |
createReplacementJoin(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
LoptJoinTree currJoinTree,
int leftIdx,
int factorToAdd,
List<Integer> newKeys,
Integer[] replacementKeys,
List<RexNode> filtersToAdd)
Creates a replacement join, projecting either dummy columns or replacement keys from the factor that doesn't actually need to be joined. |
private LoptJoinTree |
createReplacementSemiJoin(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
LoptJoinTree factTree,
int dimIdx,
List<RexNode> filtersToAdd)
In the event that a dimension table does not need to be joined because of a semijoin, this method creates a join tree that consists of a projection on top of an existing join tree. |
private RelNode |
createTopProject(LoptMultiJoin multiJoin,
LoptJoinTree joinTree,
String[] fieldNames)
Creates the topmost projection that will sit on top of the selected join ordering. |
private void |
findBestOrderings(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
RelOptRuleCall call)
Generates N optimal join orderings. |
private void |
findRemovableOuterJoins(LoptMultiJoin multiJoin)
Locates all null generating factors whose outer join can be removed. |
private void |
findRemovableSelfJoins(LoptMultiJoin multiJoin)
Locates pairs of joins that are self-joins where the join can be removed because the join condition between the two factors is an equality join on unique keys. |
private int |
getBestNextFactor(LoptMultiJoin multiJoin,
BitSet factorsToAdd,
BitSet factorsAdded,
LoptSemiJoinOptimizer semiJoinOpt,
LoptJoinTree joinTree,
List<RexNode> filtersToAdd)
Determines the best factor to be added next into a join tree. |
private Map<Integer,RelOptTable> |
getSimpleFactors(LoptMultiJoin multiJoin)
Retrieves join factors that correspond to simple table references. |
private boolean |
isJoinTree(RelNode rel)
Returns true if a relnode corresponds to a JoinRel that wasn't one of the original MultiJoinRel input factors |
static boolean |
isRemovableSelfJoin(JoinRel joinRel)
Determines whether a join is a removable self-join. |
private boolean |
isSelfJoinFilterUnique(LoptMultiJoin multiJoin,
int leftFactor,
int rightFactor,
List<RexNode> joinFilterList)
Determines if the equality join filters between two factors that map to the same table consist of unique, identical keys. |
private boolean |
needsAdjustment(LoptMultiJoin multiJoin,
int[] adjustments,
LoptJoinTree joinTree,
LoptJoinTree otherTree,
boolean selfJoin)
Sets an array indicating how much each factor in a join tree needs to be adjusted to reflect the tree's join ordering |
void |
onMatch(RelOptRuleCall call)
Receives notification about a rule match. |
private LoptJoinTree |
pushDownFactor(LoptMultiJoin multiJoin,
LoptSemiJoinOptimizer semiJoinOpt,
LoptJoinTree joinTree,
int factorToAdd,
BitSet factorsNeeded,
List<RexNode> filtersToAdd,
boolean selfJoin)
Creates a join tree where the new factor is pushed down one of the operands of the current join tree |
private boolean |
remapJoinReferences(LoptMultiJoin multiJoin,
int factor,
List<Integer> newJoinOrder,
int newPos,
int[] adjustments,
int offset,
int newOffset,
boolean alwaysUseDefault)
Sets an adjustment array based on where column references for a particular factor end up as a result of a new join ordering. |
private int |
rowWidthCost(RelNode tree)
Computes a cost for a join tree based on the row widths of the inputs into the join. |
private void |
setFactorJoinKeys(LoptMultiJoin multiJoin,
List<RexNode> filters,
BitSet joinFactors,
int factorStart,
int nFields,
BitSet joinKeys)
Locates from a list of filters those that correspond to a particular join tree. |
private void |
setJoinKey(BitSet joinKeys,
BitSet otherJoinKeys,
int ref1,
int ref2,
int firstFieldNum,
int lastFieldNum,
boolean swap)
Sets a join key if only one of the specified input references corresponds to a specified factor as determined by its field numbers. |
private RexNode |
swapFilter(RexBuilder rexBuilder,
LoptMultiJoin multiJoin,
LoptJoinTree origLeft,
LoptJoinTree origRight,
RexNode condition)
Adjusts a filter to reflect swapping of join inputs |
private boolean |
swapInputs(LoptMultiJoin multiJoin,
LoptJoinTree left,
LoptJoinTree right,
boolean selfJoin)
Swaps the operands to a join, so the smaller input is on the right. |
Methods inherited from class org.eigenbase.relopt.RelOptRule |
---|
convert, equals, equals, getOperand, getOperands, getOutConvention, getOutTrait, hashCode, matches, mergeTraitsAndConvert, mergeTraitsAndConvert, toString |
Methods inherited from class java.lang.Object |
---|
clone, finalize, getClass, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
public static final LoptOptimizeJoinRule instance
Constructor Detail |
---|
private LoptOptimizeJoinRule()
Method Detail |
---|
public void onMatch(RelOptRuleCall call)
RelOptRule
call.rels
holds the set of relational
expressions which match the operands to the rule;
call.rels[0]
is the root expression.
Typically a rule would check that the nodes are valid matches, creates
a new expression, then calls back RelOptRuleCall.transformTo(org.eigenbase.rel.RelNode)
to
register the expression.
onMatch
in class RelOptRule
call
- Rule callRelOptRule.matches(RelOptRuleCall)
private void findRemovableOuterJoins(LoptMultiJoin multiJoin)
multiJoin
- join factors being optimizedprivate void setJoinKey(BitSet joinKeys, BitSet otherJoinKeys, int ref1, int ref2, int firstFieldNum, int lastFieldNum, boolean swap)
joinKeys
- join keys to be set if a key is foundotherJoinKeys
- join keys for the other join factorref1
- first input referenceref2
- second input referencefirstFieldNum
- first field number of the factorlastFieldNum
- last field number + 1 of the factorswap
- if true, check for the desired input reference in the second
input reference parameter if the first input reference isn't the correct
oneprivate void findRemovableSelfJoins(LoptMultiJoin multiJoin)
multiJoin
- join factors being optimizedprivate Map<Integer,RelOptTable> getSimpleFactors(LoptMultiJoin multiJoin)
multiJoin
- join factors being optimized
private boolean isSelfJoinFilterUnique(LoptMultiJoin multiJoin, int leftFactor, int rightFactor, List<RexNode> joinFilterList)
multiJoin
- join factors being optimizedleftFactor
- left factor in the joinrightFactor
- right factor in the joinjoinFilterList
- list of join filters between the two factors
private void findBestOrderings(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, RelOptRuleCall call)
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins for each factorcall
- RelOptRuleCall associated with this ruleprivate RelNode createTopProject(LoptMultiJoin multiJoin, LoptJoinTree joinTree, String[] fieldNames)
multiJoin
- join factors being optimizedjoinTree
- selected join orderingfieldNames
- fieldnames corresponding to the projection expressions
private Double computeJoinCardinality(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree joinTree, List<RexNode> filters, int factor)
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins chosen for each factorjoinTree
- the join tree that the factor is being joined withfilters
- possible join filters to select fromfactor
- the factor being added
private void setFactorJoinKeys(LoptMultiJoin multiJoin, List<RexNode> filters, BitSet joinFactors, int factorStart, int nFields, BitSet joinKeys)
multiJoin
- join factors being optimizedfilters
- list of join filtersjoinFactors
- bitmap containing the factors in a particular join
treefactorStart
- the initial offset of the factor whose join keys will
be extractednFields
- the number of fields in the factor whose join keys will be
extractedjoinKeys
- the bitmap that will be set with the join keysprivate LoptJoinTree createOrdering(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, int firstFactor)
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins for each factorfirstFactor
- first factor in the tree
private int getBestNextFactor(LoptMultiJoin multiJoin, BitSet factorsToAdd, BitSet factorsAdded, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree joinTree, List<RexNode> filtersToAdd)
multiJoin
- join factors being optimizedfactorsToAdd
- factors to choose from to add nextfactorsAdded
- factors that have already been added to the join treesemiJoinOpt
- optimal semijoins for each factorjoinTree
- join tree constructed thus farfiltersToAdd
- remaining filters that need to be added
private boolean isJoinTree(RelNode rel)
private LoptJoinTree addFactorToTree(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree joinTree, int factorToAdd, BitSet factorsNeeded, List<RexNode> filtersToAdd, boolean selfJoin)
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins for each factorjoinTree
- current join treefactorToAdd
- new factor to be addedfactorsNeeded
- factors that must precede the factor to be addedfiltersToAdd
- filters remaining to be added; filters added to the
new join tree are removed from the listselfJoin
- true if the join being created is a self-join that's
removable
private int rowWidthCost(RelNode tree)
tree
- a tree of RelNodes
private LoptJoinTree pushDownFactor(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree joinTree, int factorToAdd, BitSet factorsNeeded, List<RexNode> filtersToAdd, boolean selfJoin)
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins for each factorjoinTree
- current join treefactorToAdd
- new factor to be addedfactorsNeeded
- factors that must precede the factor to be addedfiltersToAdd
- filters remaining to be added; filters that are added
to the join tree are removed from the listselfJoin
- true if the factor being added is part of a removable
self-join
private LoptJoinTree addToTop(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree joinTree, int factorToAdd, List<RexNode> filtersToAdd, boolean selfJoin)
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins for each factorjoinTree
- current join treefactorToAdd
- new factor to be addedfiltersToAdd
- filters remaining to be added; modifies the list to
remove filters that can be added to the join treeselfJoin
- true if the join being created is a self-join that's
removable
private RexNode addFilters(LoptMultiJoin multiJoin, LoptJoinTree leftTree, int leftIdx, LoptJoinTree rightTree, List<RexNode> filtersToAdd, boolean adjust)
multiJoin
- join factors being optimizedleftTree
- left subtree of the join treeleftIdx
- if >=0, only consider filters that reference leftIdx in
leftTree; otherwise, consider all filters that reference any factor in
leftTreerightTree
- right subtree of the join treefiltersToAdd
- remaining join filters that need to be added; those
that are added are removed from the listadjust
- if true, adjust filter to reflect new join ordering
private RexNode adjustFilter(LoptMultiJoin multiJoin, LoptJoinTree left, LoptJoinTree right, RexNode condition, int factorAdded, List<Integer> origJoinOrder, RelDataTypeField[] origFields)
multiJoin
- join factors being optimizedleft
- left subtree of the joinright
- right subtree of the joincondition
- current join conditionfactorAdded
- index corresponding to the newly added factororigJoinOrder
- original join order, before factor was pushed into
the treeorigFields
- fields from the original join before the factor was
added
private boolean remapJoinReferences(LoptMultiJoin multiJoin, int factor, List<Integer> newJoinOrder, int newPos, int[] adjustments, int offset, int newOffset, boolean alwaysUseDefault)
If the factor is not the right factor in a removable self-join, then it needs to be adjusted as follows:
If the factor is the right factor in a removable self-join and its column reference can be mapped to the left factor in the self-join, then:
multiJoin
- join factors being optimizedfactor
- the factor whose references are being adjustednewJoinOrder
- the new join ordering containing the factornewPos
- the position of the factor in the new join orderingadjustments
- the adjustments array that will be setoffset
- the starting offset within the original join ordering for
the columns of the factor being adjustednewOffset
- the new starting offset in the new join ordering for the
columns of the factor being adjustedalwaysUseDefault
- always use the default adjustment value
regardless of whether the factor is the right factor in a removable
self-join
private LoptJoinTree createReplacementSemiJoin(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree factTree, int dimIdx, List<RexNode> filtersToAdd)
The projection created on top of the join tree mimics a join of the fact and dimension tables. In order for the dimension table to have been removed, the only fields referenced from the dimension table are its dimension keys. Therefore, we can replace these dimension fields with the fields corresponding to the semijoin keys from the fact table in the projection.
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins for each factorfactTree
- existing join tree containing the fact tabledimIdx
- dimension table factor idfiltersToAdd
- filters remaining to be added; filters added to the
new join tree are removed from the list
private LoptJoinTree createReplacementJoin(LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree currJoinTree, int leftIdx, int factorToAdd, List<Integer> newKeys, Integer[] replacementKeys, List<RexNode> filtersToAdd)
multiJoin
- join factors being optimizedsemiJoinOpt
- optimal semijoins for each factorcurrJoinTree
- current join tree being added toleftIdx
- if >=0, when creating the replacement join, only consider
filters that reference leftIdx in currJoinTree; otherwise, consider all
filters that reference any factor in currJoinTreefactorToAdd
- new factor whose join can be removednewKeys
- join keys that need to be replacedreplacementKeys
- the keys that replace the join keys; null if we're
removing the null generating factor in an outer joinfiltersToAdd
- filters remaining to be added; filters added to the
new join tree are removed from the list
private LoptJoinTree createJoinSubtree(LoptMultiJoin multiJoin, LoptJoinTree left, LoptJoinTree right, RexNode condition, JoinRelType joinType, List<RexNode> filtersToAdd, boolean fullAdjust, boolean selfJoin)
multiJoin
- join factors being optimizedleft
- left operandright
- right operandcondition
- join conditionjoinType
- the join typefullAdjust
- true if the join condition reflects the original join
ordering and therefore has not gone through any type of adjustment yet;
otherwise, the condition has already been partially adjusted and only
needs to be further adjusted if swapping is donefiltersToAdd
- additional filters that may be added on top of the
resulting JoinRel, if the join is a left or right outer joinselfJoin
- true if the join being created is a self-join that's
removable
private RelNode addAdditionalFilters(RelNode joinTree, LoptMultiJoin multiJoin, LoptJoinTree left, LoptJoinTree right, List<RexNode> filtersToAdd)
joinTree
- current join treemultiJoin
- join factors being optimizedleft
- left side of join treeright
- right side of join treefiltersToAdd
- remaining filters
private boolean swapInputs(LoptMultiJoin multiJoin, LoptJoinTree left, LoptJoinTree right, boolean selfJoin)
Note that unlike Broadbase, we do not swap if in the join condition,
the RHS references more columns than the LHS. This can help for queries
like (select * from A,B where A.A between B.X and B.Y). By putting B on
the left, that would result in a sargable predicate with two endpoints.
However, since SargRexAnalyzer
currently
doesn't handle these type of sargable predicates, there's no point in
doing the swap for this reason.
multiJoin
- join factors being optimizedleft
- left side of join treeright
- right hand side of join treeselfJoin
- true if the join is a removable self-join
private RexNode swapFilter(RexBuilder rexBuilder, LoptMultiJoin multiJoin, LoptJoinTree origLeft, LoptJoinTree origRight, RexNode condition)
rexBuilder
- rexBuildermultiJoin
- join factors being optimizedorigLeft
- original LHS of the join tree (before swap)origRight
- original RHS of the join tree (before swap)condition
- original join condition
private boolean needsAdjustment(LoptMultiJoin multiJoin, int[] adjustments, LoptJoinTree joinTree, LoptJoinTree otherTree, boolean selfJoin)
multiJoin
- join factors being optimizedadjustments
- array to be filled outjoinTree
- join treeotherTree
- null unless joinTree only represents the left side of
the join treeselfJoin
- true if no adjustments need to be made for self-joins
public static boolean isRemovableSelfJoin(JoinRel joinRel)
joinRel
- the join
private static boolean areSelfJoinKeysUnique(RelNode leftRel, RelNode rightRel, RexNode joinFilters)
leftRel
- left side of the joinrightRel
- right side of the joinjoinFilters
- the join condition
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |