Search in sources :

Example 41 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class InlineAggregation method inlineAggregationApply.

AbstractPlanNode inlineAggregationApply(AbstractPlanNode plan) {
    // check for an aggregation of the right form
    if (!(plan instanceof AggregatePlanNode)) {
        return plan;
    }
    assert (plan.getChildCount() == 1);
    AggregatePlanNode aggplan = (AggregatePlanNode) plan;
    // Assuming all AggregatePlanNode has not been inlined before this microoptimization
    AbstractPlanNode child = aggplan.getChild(0);
    // EE Currently support: seqscan + indexscan
    if (child.getPlanNodeType() != PlanNodeType.SEQSCAN && child.getPlanNodeType() != PlanNodeType.INDEXSCAN && child.getPlanNodeType() != PlanNodeType.NESTLOOP && child.getPlanNodeType() != PlanNodeType.NESTLOOPINDEX) {
        return plan;
    }
    if (child.getPlanNodeType() == PlanNodeType.INDEXSCAN) {
        // Currently do not conflict with the optimized MIN/MAX
        // because of the big amount of tests changed.
        IndexScanPlanNode isp = (IndexScanPlanNode) child;
        LimitPlanNode limit = (LimitPlanNode) isp.getInlinePlanNode(PlanNodeType.LIMIT);
        if (limit != null && (aggplan.isTableMin() || aggplan.isTableMax())) {
            // Optimized MIN/MAX
            if (limit.getLimit() == 1 && limit.getOffset() == 0) {
                return plan;
            }
        }
    }
    // Inline aggregate node
    AbstractPlanNode parent = null;
    if (aggplan.getParentCount() == 1) {
        parent = aggplan.getParent(0);
    }
    child.addInlinePlanNode(aggplan);
    child.clearParents();
    if (parent != null) {
        parent.replaceChild(aggplan, child);
    }
    return child;
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) AggregatePlanNode(org.voltdb.plannodes.AggregatePlanNode) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) LimitPlanNode(org.voltdb.plannodes.LimitPlanNode)

Example 42 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class SubPlanAssembler method getIndexAccessPlanForTable.

/**
     * Get an index scan access plan for a table.
     *
     * @param tableAliasIndex The table to get data from.
     * @param path The access path to access the data in the table (index/scan/etc).
     * @return An index scan plan node OR,
               in one edge case, an NLIJ of a MaterializedScan and an index scan plan node.
     */
private static AbstractPlanNode getIndexAccessPlanForTable(StmtTableScan tableScan, AccessPath path) {
    // now assume this will be an index scan and get the relevant index
    Index index = path.index;
    IndexScanPlanNode scanNode = new IndexScanPlanNode(tableScan, index);
    AbstractPlanNode resultNode = scanNode;
    // set sortDirection here because it might be used for IN list
    scanNode.setSortDirection(path.sortDirection);
    // the one element of indexExprs.
    for (AbstractExpression expr : path.indexExprs) {
        if (path.lookupType == IndexLookupType.GEO_CONTAINS) {
            scanNode.addSearchKeyExpression(expr);
            scanNode.addCompareNotDistinctFlag(false);
            continue;
        }
        AbstractExpression exprRightChild = expr.getRight();
        assert (exprRightChild != null);
        if (expr.getExpressionType() == ExpressionType.COMPARE_IN) {
            // Replace this method's result with an injected NLIJ.
            resultNode = injectIndexedJoinWithMaterializedScan(exprRightChild, scanNode);
            // Extract a TVE from the LHS MaterializedScan for use by the IndexScan in its new role.
            MaterializedScanPlanNode matscan = (MaterializedScanPlanNode) resultNode.getChild(0);
            AbstractExpression elemExpr = matscan.getOutputExpression();
            assert (elemExpr != null);
            // Replace the IN LIST condition in the end expression referencing all the list elements
            // with a more efficient equality filter referencing the TVE for each element in turn.
            replaceInListFilterWithEqualityFilter(path.endExprs, exprRightChild, elemExpr);
            // Set up the similar VectorValue --> TVE replacement of the search key expression.
            exprRightChild = elemExpr;
        }
        if (exprRightChild instanceof AbstractSubqueryExpression) {
            // DEAD CODE with the guards on index: ENG-8203
            assert (false);
        }
        scanNode.addSearchKeyExpression(exprRightChild);
        // If the index expression is an "IS NOT DISTINCT FROM" comparison, let the NULL values go through. (ENG-11096)
        scanNode.addCompareNotDistinctFlag(expr.getExpressionType() == ExpressionType.COMPARE_NOTDISTINCT);
    }
    // create the IndexScanNode with all its metadata
    scanNode.setLookupType(path.lookupType);
    scanNode.setBindings(path.bindings);
    scanNode.setEndExpression(ExpressionUtil.combinePredicates(path.endExprs));
    scanNode.setPredicate(path.otherExprs);
    // Propagate the sorting information
    // into the scan node from the access path.
    // The initial expression is needed to control a (short?) forward scan to adjust the start of a reverse
    // iteration after it had to initially settle for starting at "greater than a prefix key".
    scanNode.setInitialExpression(ExpressionUtil.combinePredicates(path.initialExpr));
    scanNode.setSkipNullPredicate();
    scanNode.setEliminatedPostFilters(path.eliminatedPostExprs);
    if (scanNode instanceof IndexSortablePlanNode) {
        IndexUseForOrderBy indexUse = ((IndexSortablePlanNode) scanNode).indexUse();
        indexUse.setWindowFunctionUsesIndex(path.m_windowFunctionUsesIndex);
        indexUse.setSortOrderFromIndexScan(path.sortDirection);
        indexUse.setWindowFunctionIsCompatibleWithOrderBy(path.m_stmtOrderByIsCompatible);
        indexUse.setFinalExpressionOrderFromIndexScan(path.m_finalExpressionOrder);
    }
    return resultNode;
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) IndexSortablePlanNode(org.voltdb.plannodes.IndexSortablePlanNode) AbstractExpression(org.voltdb.expressions.AbstractExpression) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) MaterializedScanPlanNode(org.voltdb.plannodes.MaterializedScanPlanNode) AbstractSubqueryExpression(org.voltdb.expressions.AbstractSubqueryExpression) Index(org.voltdb.catalog.Index) IndexUseForOrderBy(org.voltdb.plannodes.IndexUseForOrderBy)

Example 43 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class ScanDeterminizer method recursivelyApply.

private static AbstractPlanNode recursivelyApply(AbstractPlanNode plan) {
    assert (plan != null);
    // depth first:
    //     Find Sequential Scan node.
    //     Replace with any unique tree index scan if possible.
    ArrayList<AbstractPlanNode> children = new ArrayList<AbstractPlanNode>();
    for (int i = 0; i < plan.getChildCount(); i++) {
        children.add(plan.getChild(i));
    }
    for (AbstractPlanNode child : children) {
        // TODO this will break when children feed multiple parents
        AbstractPlanNode newChild = recursivelyApply(child);
        // Do a graft into the (parent) plan only if a replacement for a child was found.
        if (newChild == child) {
            continue;
        }
        boolean replaced = plan.replaceChild(child, newChild);
        assert (replaced);
    }
    // skip the meat if this isn't a scan node
    if (!(plan instanceof SeqScanPlanNode)) {
        return plan;
    }
    SeqScanPlanNode scanNode = (SeqScanPlanNode) plan;
    if (scanNode.isSubQuery()) {
        // This is a sub-query and can't have indexes
        return plan;
    }
    // got here? we're got ourselves a sequential scan over a real table
    assert (scanNode.getChildCount() == 0);
    StmtTableScan tableScan = scanNode.getTableScan();
    assert (tableScan != null);
    Index indexToScan = null;
    // does anything for performance at all.
    for (Index index : tableScan.getIndexes()) {
        // skip non-unique indexes
        if (index.getUnique() == false) {
            continue;
        } else // skip hash indexes
        if (index.getType() != IndexType.BALANCED_TREE.getValue()) {
            continue;
        } else // skip partial indexes
        if (!index.getPredicatejson().isEmpty()) {
            continue;
        } else if (indexToScan == null || CatalogUtil.getCatalogIndexSize(indexToScan) > CatalogUtil.getCatalogIndexSize(index)) {
            indexToScan = index;
        }
    }
    if (indexToScan == null) {
        return plan;
    }
    // make an index node from the scan node
    IndexScanPlanNode indexScanNode = new IndexScanPlanNode(scanNode, null, indexToScan, SortDirectionType.ASC);
    indexScanNode.setForDeterminismOnly();
    return indexScanNode;
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) SeqScanPlanNode(org.voltdb.plannodes.SeqScanPlanNode) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) ArrayList(java.util.ArrayList) Index(org.voltdb.catalog.Index) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Example 44 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class TestMultipleOuterJoinPlans method verifyJoinNode.

private void verifyJoinNode(AbstractPlanNode n, PlanNodeType nodeType, JoinType joinType, ExpressionType preJoinExpressionType, ExpressionType joinExpressionType, ExpressionType whereExpressionType, PlanNodeType outerNodeType, PlanNodeType innerNodeType, String outerTableAlias, String innerTableAlias) {
    assertEquals(nodeType, n.getPlanNodeType());
    AbstractJoinPlanNode jn = (AbstractJoinPlanNode) n;
    assertEquals(joinType, jn.getJoinType());
    if (preJoinExpressionType != null) {
        assertEquals(preJoinExpressionType, jn.getPreJoinPredicate().getExpressionType());
    } else {
        assertNull(jn.getPreJoinPredicate());
    }
    if (joinExpressionType != null) {
        assertEquals(joinExpressionType, jn.getJoinPredicate().getExpressionType());
    } else {
        assertNull(jn.getJoinPredicate());
    }
    if (whereExpressionType != null) {
        assertEquals(whereExpressionType, jn.getWherePredicate().getExpressionType());
    } else {
        assertNull(jn.getWherePredicate());
    }
    assertEquals(outerNodeType, jn.getChild(0).getPlanNodeType());
    if (outerTableAlias != null) {
        assertEquals(outerTableAlias, ((AbstractScanPlanNode) jn.getChild(0)).getTargetTableAlias());
    }
    if (nodeType == PlanNodeType.NESTLOOP) {
        assertEquals(innerNodeType, jn.getChild(1).getPlanNodeType());
    }
    if (innerTableAlias != null) {
        if (nodeType == PlanNodeType.NESTLOOP) {
            assertEquals(innerTableAlias, ((AbstractScanPlanNode) jn.getChild(1)).getTargetTableAlias());
        } else {
            IndexScanPlanNode sn = (IndexScanPlanNode) jn.getInlinePlanNode(PlanNodeType.INDEXSCAN);
            assertEquals(innerTableAlias, sn.getTargetTableAlias());
        }
    }
}
Also used : IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) AbstractJoinPlanNode(org.voltdb.plannodes.AbstractJoinPlanNode)

Example 45 with IndexScanPlanNode

use of org.voltdb.plannodes.IndexScanPlanNode in project voltdb by VoltDB.

the class TestPlansJoin method perJoinOpTestIndexJoinConditions.

private void perJoinOpTestIndexJoinConditions(JoinOp joinOp) {
    String query;
    AbstractPlanNode pn;
    AbstractPlanNode node;
    NestLoopPlanNode nlj;
    NestLoopIndexPlanNode nlij;
    IndexScanPlanNode indexScan;
    AbstractExpression predicate;
    SeqScanPlanNode seqScan;
    query = "SELECT * FROM R3, R2 WHERE R3.A" + joinOp + "R2.A AND R3.C > 0 AND R2.C >= 5";
    pn = compileToTopDownTree(query, 4, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX, PlanNodeType.SEQSCAN);
    node = followAssertedLeftChain(pn, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX);
    nlij = (NestLoopIndexPlanNode) node;
    assertNull(nlij.getJoinPredicate());
    indexScan = nlij.getInlineIndexScan();
    assertEquals(IndexLookupType.EQ, indexScan.getLookupType());
    predicate = indexScan.getEndExpression();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    predicate = indexScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHAN, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
    seqScan = (SeqScanPlanNode) nlij.getChild(0);
    predicate = seqScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHANOREQUALTO, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
    query = "SELECT * FROM R3 JOIN R2 ON R3.A" + joinOp + "R2.A WHERE R3.C > 0 AND R2.C >= 5";
    pn = compileToTopDownTree(query, 4, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX, PlanNodeType.SEQSCAN);
    node = followAssertedLeftChain(pn, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX);
    nlij = (NestLoopIndexPlanNode) node;
    assertNull(nlij.getJoinPredicate());
    indexScan = nlij.getInlineIndexScan();
    assertEquals(IndexLookupType.EQ, indexScan.getLookupType());
    predicate = indexScan.getEndExpression();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    predicate = indexScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHAN, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
    seqScan = (SeqScanPlanNode) nlij.getChild(0);
    predicate = seqScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHANOREQUALTO, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
    query = "SELECT * FROM R3 JOIN R2 USING(A) WHERE R3.C > 0 AND R2.C >= 5";
    pn = compileToTopDownTree(query, 3, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX, PlanNodeType.SEQSCAN);
    node = followAssertedLeftChain(pn, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOPINDEX);
    nlij = (NestLoopIndexPlanNode) node;
    assertNull(nlij.getJoinPredicate());
    indexScan = nlij.getInlineIndexScan();
    assertEquals(IndexLookupType.EQ, indexScan.getLookupType());
    predicate = indexScan.getEndExpression();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    predicate = indexScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHAN, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
    seqScan = (SeqScanPlanNode) nlij.getChild(0);
    predicate = seqScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHANOREQUALTO, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
    query = "SELECT * FROM R3 JOIN R2 ON R3.A" + joinOp + " R2.A JOIN R1 ON R2.A" + joinOp + "R1.A WHERE R3.C > 0 AND R2.C >= 5";
    pn = compileToTopDownTree(query, 7, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOP, PlanNodeType.NESTLOOPINDEX, PlanNodeType.SEQSCAN, PlanNodeType.SEQSCAN);
    node = followAssertedLeftChain(pn, PlanNodeType.SEND, PlanNodeType.PROJECTION, PlanNodeType.NESTLOOP);
    nlj = (NestLoopPlanNode) node;
    assertNull(nlj.getPreJoinPredicate());
    predicate = nlj.getJoinPredicate();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    assertNull(nlj.getWherePredicate());
    nlij = (NestLoopIndexPlanNode) nlj.getChild(0);
    indexScan = nlij.getInlineIndexScan();
    assertEquals(IndexLookupType.EQ, indexScan.getLookupType());
    predicate = indexScan.getEndExpression();
    assertExprTopDownTree(predicate, joinOp.toOperator(), ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_TUPLE);
    predicate = indexScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHAN, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
    seqScan = (SeqScanPlanNode) nlij.getChild(0);
    predicate = seqScan.getPredicate();
    assertExprTopDownTree(predicate, ExpressionType.COMPARE_GREATERTHANOREQUALTO, ExpressionType.VALUE_TUPLE, ExpressionType.VALUE_CONSTANT);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) SeqScanPlanNode(org.voltdb.plannodes.SeqScanPlanNode) AbstractExpression(org.voltdb.expressions.AbstractExpression) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) NestLoopPlanNode(org.voltdb.plannodes.NestLoopPlanNode) NestLoopIndexPlanNode(org.voltdb.plannodes.NestLoopIndexPlanNode)

Aggregations

IndexScanPlanNode (org.voltdb.plannodes.IndexScanPlanNode)60 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)48 AbstractExpression (org.voltdb.expressions.AbstractExpression)22 NestLoopIndexPlanNode (org.voltdb.plannodes.NestLoopIndexPlanNode)15 SeqScanPlanNode (org.voltdb.plannodes.SeqScanPlanNode)14 NestLoopPlanNode (org.voltdb.plannodes.NestLoopPlanNode)11 ProjectionPlanNode (org.voltdb.plannodes.ProjectionPlanNode)8 AggregatePlanNode (org.voltdb.plannodes.AggregatePlanNode)7 OrderByPlanNode (org.voltdb.plannodes.OrderByPlanNode)6 ArrayList (java.util.ArrayList)5 Index (org.voltdb.catalog.Index)5 ReceivePlanNode (org.voltdb.plannodes.ReceivePlanNode)5 AbstractReceivePlanNode (org.voltdb.plannodes.AbstractReceivePlanNode)4 AbstractScanPlanNode (org.voltdb.plannodes.AbstractScanPlanNode)4 HashAggregatePlanNode (org.voltdb.plannodes.HashAggregatePlanNode)4 SendPlanNode (org.voltdb.plannodes.SendPlanNode)4 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)3 IndexCountPlanNode (org.voltdb.plannodes.IndexCountPlanNode)3 StmtTableScan (org.voltdb.planner.parseinfo.StmtTableScan)2 AbstractJoinPlanNode (org.voltdb.plannodes.AbstractJoinPlanNode)2