Search in sources :

Example 1 with IndexCountPlanNode

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

the class ReplaceWithIndexCounter method recursivelyApply.

@Override
protected AbstractPlanNode recursivelyApply(AbstractPlanNode plan) {
    assert (plan != null);
    // depth first:
    //     find AggregatePlanNode with exactly one child
    //     where that child is an AbstractScanPlanNode.
    //     Replace any qualifying AggregatePlanNode / AbstractScanPlanNode pair
    //     with an IndexCountPlanNode or TableCountPlanNode
    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 (true == replaced);
    }
    // check for an aggregation of the right form
    if ((plan instanceof AggregatePlanNode) == false)
        return plan;
    assert (plan.getChildCount() == 1);
    AggregatePlanNode aggplan = (AggregatePlanNode) plan;
    // ENG-6131 fixed here.
    if (!(aggplan.isTableCountStar() || aggplan.isTableNonDistinctCountConstant() || aggplan.isTableCountNonDistinctNullableColumn())) {
        return plan;
    }
    AbstractPlanNode child = plan.getChild(0);
    // A table count can replace a seq scan only if it has no predicates.
    if (child instanceof SeqScanPlanNode) {
        if (((SeqScanPlanNode) child).getPredicate() != null) {
            return plan;
        }
        AbstractExpression postPredicate = aggplan.getPostPredicate();
        if (postPredicate != null) {
            List<AbstractExpression> aggList = postPredicate.findAllAggregateSubexpressions();
            boolean allCountStar = true;
            for (AbstractExpression expr : aggList) {
                if (expr.getExpressionType() != ExpressionType.AGGREGATE_COUNT_STAR) {
                    allCountStar = false;
                    break;
                }
            }
            if (allCountStar) {
                return plan;
            }
        }
        if (hasInlineLimit(aggplan)) {
            // table count EE executor does not handle inline limit stuff
            return plan;
        }
        return new TableCountPlanNode((AbstractScanPlanNode) child, aggplan);
    }
    // Otherwise, optimized counts only replace particular cases of index scan.
    if ((child instanceof IndexScanPlanNode) == false)
        return plan;
    IndexScanPlanNode isp = (IndexScanPlanNode) child;
    // Guard against (possible future?) cases of indexable subquery.
    if (((IndexScanPlanNode) child).isSubQuery()) {
        return plan;
    }
    // except those (post-)predicates are artifact predicates we added for reverse scan purpose only
    if (isp.getPredicate() != null && !isp.isPredicatesOptimizableForAggregate()) {
        return plan;
    }
    // With no start or end keys, there's not much a counting index can do.
    if (isp.getEndExpression() == null && isp.getSearchKeyExpressions().size() == 0) {
        if (hasInlineLimit(aggplan)) {
            return plan;
        }
        return new TableCountPlanNode(isp, aggplan);
    }
    // check for the index's support for counting
    Index idx = isp.getCatalogIndex();
    if (!idx.getCountable()) {
        return plan;
    }
    // The core idea is that counting index needs to know the start key and end key to
    // jump to to get counts instead of actually doing any scanning.
    // Options to be determined are:
    // - whether each of the start/end keys is missing, partial (a prefix of a compund key), or complete,
    // - whether the count should include or exclude entries exactly matching each of the start/end keys.
    // Not all combinations of these options are supported;
    // unsupportable cases cause the factory method to return null.
    IndexCountPlanNode countingPlan = IndexCountPlanNode.createOrNull(isp, aggplan);
    if (countingPlan == null) {
        return plan;
    }
    return countingPlan;
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) AggregatePlanNode(org.voltdb.plannodes.AggregatePlanNode) IndexScanPlanNode(org.voltdb.plannodes.IndexScanPlanNode) ArrayList(java.util.ArrayList) Index(org.voltdb.catalog.Index) TableCountPlanNode(org.voltdb.plannodes.TableCountPlanNode) SeqScanPlanNode(org.voltdb.plannodes.SeqScanPlanNode) IndexCountPlanNode(org.voltdb.plannodes.IndexCountPlanNode) AbstractExpression(org.voltdb.expressions.AbstractExpression)

Example 2 with IndexCountPlanNode

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

the class TestPlansCount method testCountStar26.

// test with FLOAT type
public void testCountStar26() {
    List<AbstractPlanNode> pn = compileToFragments("SELECT count(*) from P1 WHERE NUM = 1 AND RATIO >= ?");
    for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
    AbstractPlanNode p = pn.get(0).getChild(0);
    assertTrue(p instanceof AggregatePlanNode);
    p = pn.get(1).getChild(0);
    assertTrue(p instanceof IndexCountPlanNode);
    pn = compileToFragments("SELECT count(1) from P1 WHERE NUM = 1 AND RATIO >= ?");
    for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
    p = pn.get(0).getChild(0);
    assertTrue(p instanceof AggregatePlanNode);
    p = pn.get(1).getChild(0);
    assertTrue(p instanceof IndexCountPlanNode);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) IndexCountPlanNode(org.voltdb.plannodes.IndexCountPlanNode) AggregatePlanNode(org.voltdb.plannodes.AggregatePlanNode)

Example 3 with IndexCountPlanNode

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

the class TestPlansCount method checkIndexCounter.

/**
     * Check Whether or not the original plan is replaced with CountingIndexPlanNode.
     *
     * @param pn
     *            The generated plan
     * @param isReplaceable
     *            Whether or not the original plan is replaced with CountingIndexPlanNode
     */
private void checkIndexCounter(List<AbstractPlanNode> pn, boolean isReplaceable) {
    assertTrue(pn.size() > 0);
    for (AbstractPlanNode nd : pn) {
        System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
    }
    AbstractPlanNode p = pn.get(0).getChild(0);
    if (isReplaceable)
        assertTrue(p instanceof IndexCountPlanNode);
    else
        assertTrue((p instanceof IndexCountPlanNode) == false);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) IndexCountPlanNode(org.voltdb.plannodes.IndexCountPlanNode)

Example 4 with IndexCountPlanNode

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

the class TestPlansCount method testCountStar19.

// Planner bug with Constant value overflow
public void testCountStar19() {
    List<AbstractPlanNode> pn = compileToFragments("SELECT count(*) from T2 WHERE USERNAME ='XIN' AND POINTS >= 3 AND POINTS <= 600000000000000000000000000");
    AbstractPlanNode p = pn.get(0).getChild(0);
    assertTrue((p instanceof IndexCountPlanNode) == false);
    pn = compileToFragments("SELECT count(1) from T2 WHERE USERNAME ='XIN' AND POINTS >= 3 AND POINTS <= 600000000000000000000000000");
    p = pn.get(0).getChild(0);
    assertTrue((p instanceof IndexCountPlanNode) == false);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) IndexCountPlanNode(org.voltdb.plannodes.IndexCountPlanNode)

Example 5 with IndexCountPlanNode

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

the class TestPlansCount method testCountStar22.

// Test counting index feature with partitioned table
public void testCountStar22() {
    List<AbstractPlanNode> pn = compileToFragments("SELECT count(*) from P1 WHERE NUM < ?");
    for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
    AbstractPlanNode p = pn.get(0).getChild(0);
    assertTrue(p instanceof AggregatePlanNode);
    p = pn.get(1).getChild(0);
    assertTrue(p instanceof IndexCountPlanNode);
    pn = compileToFragments("SELECT count(1) from P1 WHERE NUM < ?");
    for (AbstractPlanNode nd : pn) System.out.println("PlanNode Explain string:\n" + nd.toExplainPlanString());
    p = pn.get(0).getChild(0);
    assertTrue(p instanceof AggregatePlanNode);
    p = pn.get(1).getChild(0);
    assertTrue(p instanceof IndexCountPlanNode);
}
Also used : AbstractPlanNode(org.voltdb.plannodes.AbstractPlanNode) IndexCountPlanNode(org.voltdb.plannodes.IndexCountPlanNode) AggregatePlanNode(org.voltdb.plannodes.AggregatePlanNode)

Aggregations

IndexCountPlanNode (org.voltdb.plannodes.IndexCountPlanNode)8 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)6 AggregatePlanNode (org.voltdb.plannodes.AggregatePlanNode)3 IndexScanPlanNode (org.voltdb.plannodes.IndexScanPlanNode)3 AbstractExpression (org.voltdb.expressions.AbstractExpression)2 ArrayList (java.util.ArrayList)1 BitSet (java.util.BitSet)1 Index (org.voltdb.catalog.Index)1 SeqScanPlanNode (org.voltdb.plannodes.SeqScanPlanNode)1 TableCountPlanNode (org.voltdb.plannodes.TableCountPlanNode)1