Search in sources :

Example 1 with RowFilter

use of org.apache.cassandra.db.filter.RowFilter in project cassandra by apache.

the class SecondaryIndexManager method getBestIndexFor.

/**
     * Called at query time to choose which (if any) of the registered index implementations to use for a given query.
     *
     * This is a two step processes, firstly compiling the set of searchable indexes then choosing the one which reduces
     * the search space the most.
     *
     * In the first phase, if the command's RowFilter contains any custom index expressions, the indexes that they
     * specify are automatically included. Following that, the registered indexes are filtered to include only those
     * which support the standard expressions in the RowFilter.
     *
     * The filtered set then sorted by selectivity, as reported by the Index implementations' getEstimatedResultRows
     * method.
     *
     * Implementation specific validation of the target expression, either custom or standard, by the selected
     * index should be performed in the searcherFor method to ensure that we pick the right index regardless of
     * the validity of the expression.
     *
     * This method is only called once during the lifecycle of a ReadCommand and the result is
     * cached for future use when obtaining a Searcher, getting the index's underlying CFS for
     * ReadOrderGroup, or an estimate of the result size from an average index query.
     *
     * @param command ReadCommand to be executed
     * @return an Index instance, ready to use during execution of the command, or null if none
     * of the registered indexes can support the command.
     */
public Index getBestIndexFor(ReadCommand command) {
    if (indexes.isEmpty() || command.rowFilter().isEmpty())
        return null;
    Set<Index> searchableIndexes = new HashSet<>();
    for (RowFilter.Expression expression : command.rowFilter()) {
        if (expression.isCustom()) {
            // Only a single custom expression is allowed per query and, if present,
            // we want to always favour the index specified in such an expression
            RowFilter.CustomExpression customExpression = (RowFilter.CustomExpression) expression;
            logger.trace("Command contains a custom index expression, using target index {}", customExpression.getTargetIndex().name);
            Tracing.trace("Command contains a custom index expression, using target index {}", customExpression.getTargetIndex().name);
            return indexes.get(customExpression.getTargetIndex().name);
        } else if (!expression.isUserDefined()) {
            indexes.values().stream().filter(index -> index.supportsExpression(expression.column(), expression.operator())).forEach(searchableIndexes::add);
        }
    }
    if (searchableIndexes.isEmpty()) {
        logger.trace("No applicable indexes found");
        Tracing.trace("No applicable indexes found");
        return null;
    }
    Index selected = searchableIndexes.size() == 1 ? Iterables.getOnlyElement(searchableIndexes) : searchableIndexes.stream().min((a, b) -> Longs.compare(a.getEstimatedResultRows(), b.getEstimatedResultRows())).orElseThrow(() -> new AssertionError("Could not select most selective index"));
    // pay for an additional threadlocal get() rather than build the strings unnecessarily
    if (Tracing.isTracing()) {
        Tracing.trace("Index mean cardinalities are {}. Scanning with {}.", searchableIndexes.stream().map(i -> i.getIndexMetadata().name + ':' + i.getEstimatedResultRows()).collect(Collectors.joining(",")), selected.getIndexMetadata().name);
    }
    return selected;
}
Also used : RowFilter(org.apache.cassandra.db.filter.RowFilter) CassandraIndex(org.apache.cassandra.index.internal.CassandraIndex)

Example 2 with RowFilter

use of org.apache.cassandra.db.filter.RowFilter in project cassandra by apache.

the class SASIIndexTest method testSearchTimeouts.

@Test
public void testSearchTimeouts() {
    final ByteBuffer firstName = UTF8Type.instance.decompose("first_name");
    Map<String, Pair<String, Integer>> data1 = new HashMap<String, Pair<String, Integer>>() {

        {
            put("key1", Pair.create("Pavel", 14));
            put("key2", Pair.create("Pavel", 26));
            put("key3", Pair.create("Pavel", 27));
            put("key4", Pair.create("Jason", 27));
        }
    };
    ColumnFamilyStore store = loadData(data1, true);
    RowFilter filter = RowFilter.create();
    filter.add(store.metadata().getColumn(firstName), Operator.LIKE_CONTAINS, AsciiType.instance.fromString("a"));
    ReadCommand command = PartitionRangeReadCommand.create(store.metadata(), FBUtilities.nowInSeconds(), ColumnFilter.all(store.metadata()), filter, DataLimits.NONE, DataRange.allData(store.metadata().partitioner));
    try {
        new QueryPlan(store, command, 0).execute(ReadExecutionController.empty());
        Assert.fail();
    } catch (TimeQuotaExceededException e) {
    // correct behavior
    } catch (Exception e) {
        Assert.fail();
        e.printStackTrace();
    }
    try (ReadExecutionController controller = command.executionController()) {
        Set<String> rows = getKeys(new QueryPlan(store, command, DatabaseDescriptor.getRangeRpcTimeout(MILLISECONDS)).execute(controller));
        assertRows(rows, "key1", "key2", "key3", "key4");
    }
}
Also used : QueryPlan(org.apache.cassandra.index.sasi.plan.QueryPlan) ByteBuffer(java.nio.ByteBuffer) TimeQuotaExceededException(org.apache.cassandra.index.sasi.exceptions.TimeQuotaExceededException) ConfigurationException(org.apache.cassandra.exceptions.ConfigurationException) TimeQuotaExceededException(org.apache.cassandra.index.sasi.exceptions.TimeQuotaExceededException) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) IOException(java.io.IOException) MarshalException(org.apache.cassandra.serializers.MarshalException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RowFilter(org.apache.cassandra.db.filter.RowFilter) Pair(org.apache.cassandra.utils.Pair)

Example 3 with RowFilter

use of org.apache.cassandra.db.filter.RowFilter in project spoon by INRIA.

the class SecondaryIndexManager method getBestIndexFor.

/**
 * Called at query time to choose which (if any) of the registered index implementations to use for a given query.
 *
 * This is a two step processes, firstly compiling the set of searchable indexes then choosing the one which reduces
 * the search space the most.
 *
 * In the first phase, if the command's RowFilter contains any custom index expressions, the indexes that they
 * specify are automatically included. Following that, the registered indexes are filtered to include only those
 * which support the standard expressions in the RowFilter.
 *
 * The filtered set then sorted by selectivity, as reported by the Index implementations' getEstimatedResultRows
 * method.
 *
 * Implementation specific validation of the target expression, either custom or standard, by the selected
 * index should be performed in the searcherFor method to ensure that we pick the right index regardless of
 * the validity of the expression.
 *
 * This method is only called once during the lifecycle of a ReadCommand and the result is
 * cached for future use when obtaining a Searcher, getting the index's underlying CFS for
 * ReadOrderGroup, or an estimate of the result size from an average index query.
 *
 * @param command ReadCommand to be executed
 * @return an Index instance, ready to use during execution of the command, or null if none
 * of the registered indexes can support the command.
 */
public Index getBestIndexFor(ReadCommand command) {
    if (indexes.isEmpty() || command.rowFilter().isEmpty())
        return null;
    Set<Index> searchableIndexes = new HashSet<>();
    for (RowFilter.Expression expression : command.rowFilter()) {
        if (expression.isCustom()) {
            // Only a single custom expression is allowed per query and, if present,
            // we want to always favour the index specified in such an expression
            RowFilter.CustomExpression customExpression = (RowFilter.CustomExpression) expression;
            logger.trace("Command contains a custom index expression, using target index {}", customExpression.getTargetIndex().name);
            Tracing.trace("Command contains a custom index expression, using target index {}", customExpression.getTargetIndex().name);
            return indexes.get(customExpression.getTargetIndex().name);
        } else {
            indexes.values().stream().filter(index -> index.supportsExpression(expression.column(), expression.operator())).forEach(searchableIndexes::add);
        }
    }
    if (searchableIndexes.isEmpty()) {
        logger.trace("No applicable indexes found");
        Tracing.trace("No applicable indexes found");
        return null;
    }
    Index selected = searchableIndexes.size() == 1 ? Iterables.getOnlyElement(searchableIndexes) : searchableIndexes.stream().min((a, b) -> Longs.compare(a.getEstimatedResultRows(), b.getEstimatedResultRows())).orElseThrow(() -> new AssertionError("Could not select most selective index"));
    // pay for an additional threadlocal get() rather than build the strings unnecessarily
    if (Tracing.isTracing()) {
        Tracing.trace("Index mean cardinalities are {}. Scanning with {}.", searchableIndexes.stream().map(i -> i.getIndexMetadata().name + ':' + i.getEstimatedResultRows()).collect(Collectors.joining(",")), selected.getIndexMetadata().name);
    }
    return selected;
}
Also used : java.util(java.util) Iterables(com.google.common.collect.Iterables) MoreExecutors(com.google.common.util.concurrent.MoreExecutors) JMXEnabledThreadPoolExecutor(org.apache.cassandra.concurrent.JMXEnabledThreadPoolExecutor) CompactionManager(org.apache.cassandra.db.compaction.CompactionManager) PartitionUpdate(org.apache.cassandra.db.partitions.PartitionUpdate) SSTableSet(org.apache.cassandra.db.lifecycle.SSTableSet) LoggerFactory(org.slf4j.LoggerFactory) org.apache.cassandra.db(org.apache.cassandra.db) Constructor(java.lang.reflect.Constructor) Function(java.util.function.Function) StringUtils(org.apache.commons.lang3.StringUtils) SSTableReader(org.apache.cassandra.io.sstable.format.SSTableReader) Indexes(org.apache.cassandra.schema.Indexes) org.apache.cassandra.db.rows(org.apache.cassandra.db.rows) OpOrder(org.apache.cassandra.utils.concurrent.OpOrder) Strings(com.google.common.base.Strings) org.apache.cassandra.index.transactions(org.apache.cassandra.index.transactions) IndexTarget(org.apache.cassandra.cql3.statements.IndexTarget) ReducingKeyIterator(org.apache.cassandra.io.sstable.ReducingKeyIterator) Refs(org.apache.cassandra.utils.concurrent.Refs) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) Longs(com.google.common.primitives.Longs) ColumnDefinition(org.apache.cassandra.config.ColumnDefinition) ImmutableSet(com.google.common.collect.ImmutableSet) Logger(org.slf4j.Logger) RowFilter(org.apache.cassandra.db.filter.RowFilter) FBUtilities(org.apache.cassandra.utils.FBUtilities) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) java.util.concurrent(java.util.concurrent) Tracing(org.apache.cassandra.tracing.Tracing) Collectors(java.util.stream.Collectors) Maps(com.google.common.collect.Maps) Futures(com.google.common.util.concurrent.Futures) NamedThreadFactory(org.apache.cassandra.concurrent.NamedThreadFactory) CassandraIndex(org.apache.cassandra.index.internal.CassandraIndex) Stream(java.util.stream.Stream) StageManager(org.apache.cassandra.concurrent.StageManager) Joiner(com.google.common.base.Joiner) View(org.apache.cassandra.db.lifecycle.View) RowFilter(org.apache.cassandra.db.filter.RowFilter) CassandraIndex(org.apache.cassandra.index.internal.CassandraIndex)

Example 4 with RowFilter

use of org.apache.cassandra.db.filter.RowFilter in project cassandra by apache.

the class SecondaryIndexManager method getBestIndexFor.

/**
 * Called at query time to choose which (if any) of the registered index implementations to use for a given query.
 * <p>
 * This is a two step processes, firstly compiling the set of searchable indexes then choosing the one which reduces
 * the search space the most.
 * <p>
 * In the first phase, if the command's RowFilter contains any custom index expressions, the indexes that they
 * specify are automatically included. Following that, the registered indexes are filtered to include only those
 * which support the standard expressions in the RowFilter.
 * <p>
 * The filtered set then sorted by selectivity, as reported by the Index implementations' getEstimatedResultRows
 * method.
 * <p>
 * Implementation specific validation of the target expression, either custom or standard, by the selected
 * index should be performed in the searcherFor method to ensure that we pick the right index regardless of
 * the validity of the expression.
 * <p>
 * This method is only called once during the lifecycle of a ReadCommand and the result is
 * cached for future use when obtaining a Searcher, getting the index's underlying CFS for
 * ReadOrderGroup, or an estimate of the result size from an average index query.
 *
 * @param rowFilter RowFilter of the command to be executed
 * @return an Index instance, ready to use during execution of the command, or null if none
 * of the registered indexes can support the command.
 */
public Index getBestIndexFor(RowFilter rowFilter) {
    if (indexes.isEmpty() || rowFilter.isEmpty())
        return null;
    Set<Index> searchableIndexes = new HashSet<>();
    for (RowFilter.Expression expression : rowFilter) {
        if (expression.isCustom()) {
            // Only a single custom expression is allowed per query and, if present,
            // we want to always favour the index specified in such an expression
            RowFilter.CustomExpression customExpression = (RowFilter.CustomExpression) expression;
            logger.trace("Command contains a custom index expression, using target index {}", customExpression.getTargetIndex().name);
            Tracing.trace("Command contains a custom index expression, using target index {}", customExpression.getTargetIndex().name);
            return indexes.get(customExpression.getTargetIndex().name);
        } else if (!expression.isUserDefined()) {
            indexes.values().stream().filter(index -> index.supportsExpression(expression.column(), expression.operator())).forEach(searchableIndexes::add);
        }
    }
    if (searchableIndexes.isEmpty()) {
        logger.trace("No applicable indexes found");
        Tracing.trace("No applicable indexes found");
        return null;
    }
    Index selected = searchableIndexes.size() == 1 ? Iterables.getOnlyElement(searchableIndexes) : searchableIndexes.stream().min((a, b) -> Longs.compare(a.getEstimatedResultRows(), b.getEstimatedResultRows())).orElseThrow(() -> new AssertionError("Could not select most selective index"));
    // pay for an additional threadlocal get() rather than build the strings unnecessarily
    if (Tracing.isTracing()) {
        Tracing.trace("Index mean cardinalities are {}. Scanning with {}.", searchableIndexes.stream().map(i -> i.getIndexMetadata().name + ':' + i.getEstimatedResultRows()).collect(Collectors.joining(",")), selected.getIndexMetadata().name);
    }
    return selected;
}
Also used : RowFilter(org.apache.cassandra.db.filter.RowFilter) CassandraIndex(org.apache.cassandra.index.internal.CassandraIndex)

Example 5 with RowFilter

use of org.apache.cassandra.db.filter.RowFilter in project cassandra by apache.

the class ReadCommandTest method testCountWithNoDeletedRow.

@Test
public void testCountWithNoDeletedRow() throws Exception {
    ColumnFamilyStore cfs = Keyspace.open(KEYSPACE).getColumnFamilyStore(CF5);
    String[][][] groups = new String[][][] { new String[][] { // "1" indicates to create the data, "-1" to delete the
    new String[] { "1", "key1", "aa", "a" }, // row
    new String[] { "1", "key2", "bb", "b" }, new String[] { "1", "key3", "cc", "c" } }, new String[][] { new String[] { "1", "key3", "dd", "d" }, new String[] { "1", "key2", "ee", "e" }, new String[] { "1", "key1", "ff", "f" } }, new String[][] { new String[] { "1", "key6", "aa", "a" }, new String[] { "1", "key5", "bb", "b" }, new String[] { "1", "key4", "cc", "c" } } };
    List<ByteBuffer> buffers = new ArrayList<>(groups.length);
    int nowInSeconds = FBUtilities.nowInSeconds();
    ColumnFilter columnFilter = ColumnFilter.allRegularColumnsBuilder(cfs.metadata(), false).build();
    RowFilter rowFilter = RowFilter.create();
    Slice slice = Slice.make(BufferClusteringBound.BOTTOM, BufferClusteringBound.TOP);
    ClusteringIndexSliceFilter sliceFilter = new ClusteringIndexSliceFilter(Slices.with(cfs.metadata().comparator, slice), false);
    for (String[][] group : groups) {
        cfs.truncateBlocking();
        List<SinglePartitionReadCommand> commands = new ArrayList<>(group.length);
        for (String[] data : group) {
            if (data[0].equals("1")) {
                new RowUpdateBuilder(cfs.metadata(), 0, ByteBufferUtil.bytes(data[1])).clustering(data[2]).add(data[3], ByteBufferUtil.bytes("blah")).build().apply();
            } else {
                RowUpdateBuilder.deleteRow(cfs.metadata(), FBUtilities.timestampMicros(), ByteBufferUtil.bytes(data[1]), data[2]).apply();
            }
            commands.add(SinglePartitionReadCommand.create(cfs.metadata(), nowInSeconds, columnFilter, rowFilter, DataLimits.NONE, Util.dk(data[1]), sliceFilter));
        }
        cfs.forceBlockingFlush();
        ReadQuery query = SinglePartitionReadCommand.Group.create(commands, DataLimits.NONE);
        try (ReadExecutionController executionController = query.executionController();
            UnfilteredPartitionIterator iter = query.executeLocally(executionController);
            DataOutputBuffer buffer = new DataOutputBuffer()) {
            UnfilteredPartitionIterators.serializerForIntraNode().serialize(iter, columnFilter, buffer, MessagingService.current_version);
            buffers.add(buffer.buffer());
        }
    }
    assertEquals(1, cfs.metric.tombstoneScannedHistogram.cf.getSnapshot().getMax());
}
Also used : ColumnFilter(org.apache.cassandra.db.filter.ColumnFilter) ByteBuffer(java.nio.ByteBuffer) ClusteringIndexSliceFilter(org.apache.cassandra.db.filter.ClusteringIndexSliceFilter) RowFilter(org.apache.cassandra.db.filter.RowFilter) DataOutputBuffer(org.apache.cassandra.io.util.DataOutputBuffer) Test(org.junit.Test)

Aggregations

RowFilter (org.apache.cassandra.db.filter.RowFilter)9 ByteBuffer (java.nio.ByteBuffer)4 Test (org.junit.Test)4 ClusteringIndexSliceFilter (org.apache.cassandra.db.filter.ClusteringIndexSliceFilter)3 ColumnFilter (org.apache.cassandra.db.filter.ColumnFilter)3 CassandraIndex (org.apache.cassandra.index.internal.CassandraIndex)3 DataOutputBuffer (org.apache.cassandra.io.util.DataOutputBuffer)3 InvalidRequestException (org.apache.cassandra.exceptions.InvalidRequestException)2 Joiner (com.google.common.base.Joiner)1 Strings (com.google.common.base.Strings)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Iterables (com.google.common.collect.Iterables)1 Maps (com.google.common.collect.Maps)1 Longs (com.google.common.primitives.Longs)1 Futures (com.google.common.util.concurrent.Futures)1 MoreExecutors (com.google.common.util.concurrent.MoreExecutors)1 IOException (java.io.IOException)1 Constructor (java.lang.reflect.Constructor)1 java.util (java.util)1 java.util.concurrent (java.util.concurrent)1