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;
}
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");
}
}
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;
}
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;
}
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());
}
Aggregations