Search in sources :

Example 6 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class SubPlanAssembler method getAccessPlanForTable.

/**
     * Given an access path, build the single-site or distributed plan that will
     * assess the data from the table according to the path.
     *
     * @param table The table to get data from.
     * @return The root of a plan graph to get the data.
     */
protected static AbstractPlanNode getAccessPlanForTable(JoinNode tableNode) {
    StmtTableScan tableScan = tableNode.getTableScan();
    // Access path to access the data in the table (index/scan/etc).
    AccessPath path = tableNode.m_currentAccessPath;
    assert (path != null);
    // if no index, it is a sequential scan
    if (path.index == null) {
        return getScanAccessPlanForTable(tableScan, path);
    }
    return getIndexAccessPlanForTable(tableScan, path);
}
Also used : StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Example 7 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class MaterializedViewProcessor method findBestMatchIndexForMatviewMinOrMax.

// if the materialized view has MIN / MAX, try to find an index defined on the source table
// covering all group by cols / exprs to avoid expensive tablescan.
// For now, the only acceptable index is defined exactly on the group by columns IN ORDER.
// This allows the same key to be used to do lookups on the grouped table index and the
// base table index.
// TODO: More flexible (but usually less optimal*) indexes may be allowed here and supported
// in the EE in the future including:
//   -- *indexes on the group keys listed out of order
//   -- *indexes on the group keys as a prefix before other indexed values.
//   -- (ENG-6511) indexes on the group keys PLUS the MIN/MAX argument value (to eliminate post-filtering)
// This function is mostly re-written for the fix of ENG-6511. --yzhang
private static Index findBestMatchIndexForMatviewMinOrMax(MaterializedViewInfo matviewinfo, Table srcTable, List<AbstractExpression> groupbyExprs, AbstractExpression minMaxAggExpr) {
    CatalogMap<Index> allIndexes = srcTable.getIndexes();
    StmtTableScan tableScan = new StmtTargetTableScan(srcTable);
    // Candidate index. If we can find an index covering both group-by columns and aggExpr (optimal) then we will
    // return immediately.
    // If the index found covers only group-by columns (sub-optimal), we will first cache it here.
    Index candidate = null;
    for (Index index : allIndexes) {
        // indexOptimalForMinMax == true if the index covered both the group-by columns and the min/max aggExpr.
        boolean indexOptimalForMinMax = false;
        // If minMaxAggExpr is not null, the diff can be zero or one.
        // Otherwise, for a usable index, its number of columns must agree with that of the group-by columns.
        final int diffAllowance = minMaxAggExpr == null ? 0 : 1;
        // Get all indexed exprs if there is any.
        String expressionjson = index.getExpressionsjson();
        List<AbstractExpression> indexedExprs = null;
        if (!expressionjson.isEmpty()) {
            try {
                indexedExprs = AbstractExpression.fromJSONArrayString(expressionjson, tableScan);
            } catch (JSONException e) {
                e.printStackTrace();
                assert (false);
                return null;
            }
        }
        // Get source table columns.
        List<Column> srcColumnArray = CatalogUtil.getSortedCatalogItems(srcTable.getColumns(), "index");
        MatViewIndexMatchingGroupby matchingCase = null;
        if (groupbyExprs == null) {
            // This means group-by columns are all simple columns.
            // It also means we can only access the group-by columns by colref.
            List<ColumnRef> groupbyColRefs = CatalogUtil.getSortedCatalogItems(matviewinfo.getGroupbycols(), "index");
            if (indexedExprs == null) {
                matchingCase = MatViewIndexMatchingGroupby.GB_COL_IDX_COL;
                // All the columns in the index are also simple columns, EASY! colref vs. colref
                List<ColumnRef> indexedColRefs = CatalogUtil.getSortedCatalogItems(index.getColumns(), "index");
                // indexedColRefs.size() == groupbyColRefs.size() + 1 (optimal, diffAllowance == 1)
                if (isInvalidIndexCandidate(indexedColRefs.size(), groupbyColRefs.size(), diffAllowance)) {
                    continue;
                }
                if (!isGroupbyMatchingIndex(matchingCase, groupbyColRefs, null, indexedColRefs, null, null)) {
                    continue;
                }
                if (isValidIndexCandidateForMinMax(indexedColRefs.size(), groupbyColRefs.size(), diffAllowance)) {
                    if (!isIndexOptimalForMinMax(matchingCase, minMaxAggExpr, indexedColRefs, null, srcColumnArray)) {
                        continue;
                    }
                    indexOptimalForMinMax = true;
                }
            } else {
                matchingCase = MatViewIndexMatchingGroupby.GB_COL_IDX_EXP;
                //                              for    index columns: convert    tve => col
                if (isInvalidIndexCandidate(indexedExprs.size(), groupbyColRefs.size(), diffAllowance)) {
                    continue;
                }
                if (!isGroupbyMatchingIndex(matchingCase, groupbyColRefs, null, null, indexedExprs, srcColumnArray)) {
                    continue;
                }
                if (isValidIndexCandidateForMinMax(indexedExprs.size(), groupbyColRefs.size(), diffAllowance)) {
                    if (!isIndexOptimalForMinMax(matchingCase, minMaxAggExpr, null, indexedExprs, null)) {
                        continue;
                    }
                    indexOptimalForMinMax = true;
                }
            }
        } else {
            matchingCase = MatViewIndexMatchingGroupby.GB_EXP_IDX_EXP;
            // AND, indexedExprs must not be null in this case. (yeah!)
            if (indexedExprs == null) {
                continue;
            }
            if (isInvalidIndexCandidate(indexedExprs.size(), groupbyExprs.size(), diffAllowance)) {
                continue;
            }
            if (!isGroupbyMatchingIndex(matchingCase, null, groupbyExprs, null, indexedExprs, null)) {
                continue;
            }
            if (isValidIndexCandidateForMinMax(indexedExprs.size(), groupbyExprs.size(), diffAllowance)) {
                if (!isIndexOptimalForMinMax(matchingCase, minMaxAggExpr, null, indexedExprs, null)) {
                    continue;
                }
                indexOptimalForMinMax = true;
            }
        }
        // NOW index at least covered all group-by columns (sub-optimal candidate)
        if (!index.getPredicatejson().isEmpty()) {
            // Additional check for partial indexes to make sure matview WHERE clause
            // covers the partial index predicate
            List<AbstractExpression> coveringExprs = new ArrayList<>();
            List<AbstractExpression> exactMatchCoveringExprs = new ArrayList<>();
            try {
                String encodedPredicate = matviewinfo.getPredicate();
                if (!encodedPredicate.isEmpty()) {
                    String predicate = Encoder.hexDecodeToString(encodedPredicate);
                    AbstractExpression matViewPredicate = AbstractExpression.fromJSONString(predicate, tableScan);
                    coveringExprs.addAll(ExpressionUtil.uncombineAny(matViewPredicate));
                }
            } catch (JSONException e) {
                e.printStackTrace();
                assert (false);
                return null;
            }
            String predicatejson = index.getPredicatejson();
            if (!predicatejson.isEmpty() && !SubPlanAssembler.isPartialIndexPredicateCovered(tableScan, coveringExprs, predicatejson, exactMatchCoveringExprs)) {
                // where clause -- give up on this index
                continue;
            }
        }
        // it is already the best index we can get, return immediately.
        if (indexOptimalForMinMax) {
            return index;
        }
        // otherwise wait to see if we can find something better!
        candidate = index;
    }
    return candidate;
}
Also used : ArrayList(java.util.ArrayList) JSONException(org.json_voltpatches.JSONException) Index(org.voltdb.catalog.Index) Constraint(org.voltdb.catalog.Constraint) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan) AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) StmtTargetTableScan(org.voltdb.planner.parseinfo.StmtTargetTableScan) ColumnRef(org.voltdb.catalog.ColumnRef)

Example 8 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class ParsedUnionStmt method addStmtTablesFromChildren.

private void addStmtTablesFromChildren(HashMap<String, StmtTableScan> tableAliasMap) {
    for (String alias : tableAliasMap.keySet()) {
        StmtTableScan tableScan = tableAliasMap.get(alias);
        if (m_tableAliasMap.get(alias) == null) {
            m_tableAliasMap.put(alias, tableScan);
        } else {
            // if there is a duplicate table alias in the map,
            // find a new unique name for the key
            // the value in the map are more interesting
            alias += "_" + System.currentTimeMillis();
            HashMap<String, StmtTableScan> duplicates = new HashMap<String, StmtTableScan>();
            duplicates.put(alias, tableScan);
            addStmtTablesFromChildren(duplicates);
        }
    }
}
Also used : HashMap(java.util.HashMap) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Example 9 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class ParsedSelectStmt method prepareMVBasedQueryFix.

/**
     * Prepare for the mv based distributed query fix only if it might be required.
     */
private void prepareMVBasedQueryFix() {
    // aggregation push down does not need reAggregation work.
    if (m_hasComplexGroupby) {
        m_mvFixInfo.setEdgeCaseQueryNoFixNeeded(false);
    }
    // that need to be fixed should not exceed one.
    for (StmtTableScan mvTableScan : allScans()) {
        Set<SchemaColumn> mvNewScanColumns = new HashSet<>();
        Collection<SchemaColumn> columns = mvTableScan.getScanColumns();
        // TB has no scan columns
        if (columns != null) {
            mvNewScanColumns.addAll(columns);
        }
        // also need to be checked.
        if (m_mvFixInfo.processMVBasedQueryFix(mvTableScan, mvNewScanColumns, m_joinTree, m_aggResultColumns, groupByColumns())) {
            break;
        }
    }
}
Also used : SchemaColumn(org.voltdb.plannodes.SchemaColumn) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan) HashSet(java.util.HashSet)

Example 10 with StmtTableScan

use of org.voltdb.planner.parseinfo.StmtTableScan in project voltdb by VoltDB.

the class ParsedSelectStmt method isPartitionColumnInWindowedAggregatePartitionByList.

/**
     * Return true iff all the windowed partition expressions
     * have a table partition column in their partition by list,
     * and if there is one such windowed partition expression.
     * If there are no windowed expressions, we return false.
     * Note that there can only be one windowed
     * expression currently, so this is more general than it needs to be.
     *
     * @return
     */
public boolean isPartitionColumnInWindowedAggregatePartitionByList() {
    if (getWindowFunctionExpressions().size() == 0) {
        return false;
    }
    // If we ever do, this should fail gracelessly.
    assert (getWindowFunctionExpressions().size() == 1);
    WindowFunctionExpression we = getWindowFunctionExpressions().get(0);
    List<AbstractExpression> partitionByExprs = we.getPartitionByExpressions();
    boolean foundPartExpr = false;
    for (AbstractExpression ae : partitionByExprs) {
        if (!(ae instanceof TupleValueExpression)) {
            continue;
        }
        TupleValueExpression tve = (TupleValueExpression) ae;
        String tableAlias = tve.getTableAlias();
        String columnName = tve.getColumnName();
        StmtTableScan scanTable = getStmtTableScanByAlias(tableAlias);
        if (scanTable == null || scanTable.getPartitioningColumns() == null) {
            continue;
        }
        boolean foundPartCol = false;
        for (SchemaColumn pcol : scanTable.getPartitioningColumns()) {
            if (pcol != null && pcol.getColumnName().equals(columnName)) {
                foundPartCol = true;
                break;
            }
        }
        // in this windowed expression.
        if (foundPartCol) {
            foundPartExpr = true;
            break;
        }
    }
    return foundPartExpr;
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) WindowFunctionExpression(org.voltdb.expressions.WindowFunctionExpression) SchemaColumn(org.voltdb.plannodes.SchemaColumn) StmtTableScan(org.voltdb.planner.parseinfo.StmtTableScan)

Aggregations

StmtTableScan (org.voltdb.planner.parseinfo.StmtTableScan)28 AbstractExpression (org.voltdb.expressions.AbstractExpression)16 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)9 Constraint (org.voltdb.catalog.Constraint)8 SchemaColumn (org.voltdb.plannodes.SchemaColumn)8 HashSet (java.util.HashSet)7 Table (org.voltdb.catalog.Table)7 StmtTargetTableScan (org.voltdb.planner.parseinfo.StmtTargetTableScan)7 ArrayList (java.util.ArrayList)6 Index (org.voltdb.catalog.Index)6 StmtSubqueryScan (org.voltdb.planner.parseinfo.StmtSubqueryScan)6 Set (java.util.Set)5 JSONException (org.json_voltpatches.JSONException)5 ColumnRef (org.voltdb.catalog.ColumnRef)5 ParameterValueExpression (org.voltdb.expressions.ParameterValueExpression)5 HashMap (java.util.HashMap)4 Column (org.voltdb.catalog.Column)4 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)4 TreeMap (java.util.TreeMap)3 ConstantValueExpression (org.voltdb.expressions.ConstantValueExpression)3