Skip to content

Commit

Permalink
opt: revert consolidate logic for constraining inverted indexes
Browse files Browse the repository at this point in the history
This reverts commit 5929688. It is not
strictly necessary for the new functionality in cockroachdb#122683.

Release note: None
  • Loading branch information
mgartner committed Apr 22, 2024
1 parent b133474 commit f62f22e
Showing 1 changed file with 70 additions and 49 deletions.
119 changes: 70 additions & 49 deletions pkg/sql/opt/invertedidx/inverted_index_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,11 @@ func TryFilterInvertedIndex(
) {
// Attempt to constrain the prefix columns, if there are any. If they cannot
// be constrained to single values, the index cannot be used.
columns, notNullCols := prefixCols(tabID, index)
if len(columns) > 0 {
constraint, filters, ok = constrainNonInvertedCols(
evalCtx, factory, columns, notNullCols, filters,
optionalFilters, tabID, index, checkCancellation,
)
if !ok {
return nil, nil, nil, nil, false
}
constraint, filters, ok = constrainPrefixColumns(
evalCtx, factory, filters, optionalFilters, tabID, index, checkCancellation,
)
if !ok {
return nil, nil, nil, nil, false
}

config := index.GeoConfig()
Expand Down Expand Up @@ -208,8 +204,10 @@ func TryFilterInvertedIndexBySimilarity(
checkCancellation func(),
) (_ *constraint.Constraint, remainingFilters memo.FiltersExpr, ok bool) {
md := f.Metadata()
tabMeta := md.TableMeta(tabID)
columnCount := index.ExplicitColumnCount()
prefixColumnCount := index.NonInvertedPrefixColumnCount()
ps := tabMeta.IndexPartitionLocality(index.Ordinal())

// The indexed column must be of a string-like type.
srcColOrd := index.InvertedColumn().InvertedSourceColumnOrdinal()
Expand Down Expand Up @@ -295,16 +293,47 @@ func TryFilterInvertedIndexBySimilarity(

// If the index is a multi-column index, then we need to constrain the
// prefix columns.
//
// Consolidation of a constraint converts contiguous spans into a single
// span. By definition, the consolidated span would have different start and
// end keys and could not be used for multi-column inverted index scans.
// Therefore, we only generate and check the unconsolidated constraint,
// allowing the optimizer to plan multi-column inverted index scans in more
// cases.
//
// For example, the consolidated constraint for (x IN (1, 2, 3)) is:
//
// /x: [/1 - /3]
// Prefix: 0
//
// The unconsolidated constraint for the same expression is:
//
// /x: [/1 - /1] [/2 - /2] [/3 - /3]
// Prefix: 1
//
var prefixConstraint *constraint.Constraint
prefixConstraint, remainingFilters, ok = constrainNonInvertedCols(
evalCtx, f, cols, notNullCols, filters,
optionalFilters, tabID, index, checkCancellation,
var ic idxconstraint.Instance
ic.Init(
filters, optionalFilters,
cols, notNullCols, tabMeta.ComputedCols,
tabMeta.ColsInComputedColsExpressions,
false, /* consolidate */
evalCtx, f, ps, checkCancellation,
)
if !ok {
prefixConstraint = ic.UnconsolidatedConstraint()
if prefixConstraint.Prefix(evalCtx) != prefixColumnCount {
// The prefix columns must be constrained to single values.
return nil, nil, false
}
prefixConstraint.Combine(evalCtx, con, checkCancellation)
return prefixConstraint, remainingFilters, true

// The constraint is a pointer to a field of ic. Make a copy of the
// constraint so that we no longer reference ic and it can be GC'd.
prefixConstraintCopy := *prefixConstraint

// Combine the prefix constraint and the inverted column constraint.
prefixConstraintCopy.Combine(evalCtx, con, checkCancellation)
remainingFilters = ic.RemainingFilters()
return &prefixConstraintCopy, remainingFilters, true
}

func extractConstStringDatum(expr opt.ScalarExpr) (string, bool) {
Expand Down Expand Up @@ -631,45 +660,19 @@ func evalInvertedExpr(
}
}

// prefixCols returns a slice of ordering columns for each of the non-inverted
// prefix of the index. It also returns a set of those columns that are NOT
// NULL. If the index is a single-column inverted index, the function returns
// nil ordering columns.
func prefixCols(
tabID opt.TableID, index cat.Index,
) (_ []opt.OrderingColumn, notNullCols opt.ColSet) {
prefixColumnCount := index.NonInvertedPrefixColumnCount()

// If this is a single-column inverted index, there are no prefix columns.
// constrain.
if prefixColumnCount == 0 {
return nil, opt.ColSet{}
}

prefixColumns := make([]opt.OrderingColumn, prefixColumnCount)
for i := range prefixColumns {
col := index.Column(i)
colID := tabID.ColumnID(col.Ordinal())
prefixColumns[i] = opt.MakeOrderingColumn(colID, col.Descending)
if !col.IsNullable() {
notNullCols.Add(colID)
}
}
return prefixColumns, notNullCols
}

// constrainNonInvertedCols attempts to build a constraint for the non-inverted
// constrainPrefixColumns attempts to build a constraint for the non-inverted
// prefix columns of the given index. If a constraint is successfully built, it
// is returned along with remaining filters and ok=true. The function is only
// successful if it can generate a constraint where all spans have the same
// start and end keys for all non-inverted prefix columns. This is required for
// building spans for scanning multi-column inverted indexes (see
// span.Builder.SpansFromInvertedSpans).
func constrainNonInvertedCols(
//
// If the index is a single-column inverted index, there are no prefix columns
// to constrain, and ok=true is returned.
func constrainPrefixColumns(
evalCtx *eval.Context,
factory *norm.Factory,
columns []opt.OrderingColumn,
notNullCols opt.ColSet,
filters memo.FiltersExpr,
optionalFilters memo.FiltersExpr,
tabID opt.TableID,
Expand All @@ -680,6 +683,23 @@ func constrainNonInvertedCols(
prefixColumnCount := index.NonInvertedPrefixColumnCount()
ps := tabMeta.IndexPartitionLocality(index.Ordinal())

// If this is a single-column inverted index, there are no prefix columns to
// constrain.
if prefixColumnCount == 0 {
return nil, filters, true
}

prefixColumns := make([]opt.OrderingColumn, prefixColumnCount)
var notNullCols opt.ColSet
for i := range prefixColumns {
col := index.Column(i)
colID := tabID.ColumnID(col.Ordinal())
prefixColumns[i] = opt.MakeOrderingColumn(colID, col.Descending)
if !col.IsNullable() {
notNullCols.Add(colID)
}
}

// Consolidation of a constraint converts contiguous spans into a single
// span. By definition, the consolidated span would have different start and
// end keys and could not be used for multi-column inverted index scans.
Expand All @@ -700,14 +720,15 @@ func constrainNonInvertedCols(
var ic idxconstraint.Instance
ic.Init(
filters, optionalFilters,
columns, notNullCols, tabMeta.ComputedCols,
prefixColumns, notNullCols, tabMeta.ComputedCols,
tabMeta.ColsInComputedColsExpressions,
false, /* consolidate */
evalCtx, factory, ps, checkCancellation,
)
constraint = ic.UnconsolidatedConstraint()
if constraint.Prefix(evalCtx) != prefixColumnCount {
// The prefix columns must be constrained to single values.
if constraint.Prefix(evalCtx) < prefixColumnCount {
// If all of the constraint spans do not have the same start and end keys
// for all columns, the index cannot be used.
return nil, nil, false
}

Expand Down

0 comments on commit f62f22e

Please sign in to comment.