This is an automated email from the ASF dual-hosted git repository.
maedhroz pushed a commit to branch cassandra-5.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-5.0 by this push:
new 1d7bae3697 Record latencies for SAI post-filtering reads against local
storage
1d7bae3697 is described below
commit 1d7bae3697b97e64de2c2b958427ef86a1b17731
Author: Caleb Rackliffe <[email protected]>
AuthorDate: Thu Feb 22 15:08:23 2024 -0600
Record latencies for SAI post-filtering reads against local storage
patch by Caleb Rackliffe; reviewed by Mike Adamson for CASSANDRA-18940
---
CHANGES.txt | 1 +
.../index/sai/metrics/TableQueryMetrics.java | 4 +++
.../cassandra/index/sai/plan/QueryController.java | 14 +--------
.../sai/plan/StorageAttachedIndexSearcher.java | 33 +++++++++++++---------
.../index/sai/metrics/QueryMetricsTest.java | 6 +++-
.../cassandra/index/sai/plan/OperationTest.java | 9 ++----
6 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 20e0c6e959..4f35041497 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.0-beta2
+ * Record latencies for SAI post-filtering reads against local storage
(CASSANDRA-18940)
* Fix VectorMemoryIndex#update logic to compare vectors. Fix Index view
(CASSANDRA-19168)
* Deprecate native_transport_port_ssl (CASSANDRA-19392)
* Update packaging shell includes (CASSANDRA-19283)
diff --git
a/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
b/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
index 7154df241d..987c70ef75 100644
--- a/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
+++ b/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
@@ -32,6 +32,8 @@ public class TableQueryMetrics extends AbstractMetrics
{
public static final String TABLE_QUERY_METRIC_TYPE = "TableQueryMetrics";
+ public final Timer postFilteringReadLatency;
+
private final PerQueryMetrics perQueryMetrics;
private final Counter totalQueryTimeouts;
@@ -45,6 +47,8 @@ public class TableQueryMetrics extends AbstractMetrics
perQueryMetrics = new PerQueryMetrics(table);
+ postFilteringReadLatency =
Metrics.timer(createMetricName("PostFilteringReadLatency"));
+
totalPartitionReads =
Metrics.counter(createMetricName("TotalPartitionReads"));
totalRowsFiltered =
Metrics.counter(createMetricName("TotalRowsFiltered"));
totalQueriesCompleted =
Metrics.counter(createMetricName("TotalQueriesCompleted"));
diff --git a/src/java/org/apache/cassandra/index/sai/plan/QueryController.java
b/src/java/org/apache/cassandra/index/sai/plan/QueryController.java
index 597e339aaa..d844304812 100644
--- a/src/java/org/apache/cassandra/index/sai/plan/QueryController.java
+++ b/src/java/org/apache/cassandra/index/sai/plan/QueryController.java
@@ -57,7 +57,6 @@ import
org.apache.cassandra.index.sai.iterators.KeyRangeIntersectionIterator;
import org.apache.cassandra.index.sai.iterators.KeyRangeIterator;
import org.apache.cassandra.index.sai.iterators.KeyRangeOrderingIterator;
import org.apache.cassandra.index.sai.iterators.KeyRangeUnionIterator;
-import org.apache.cassandra.index.sai.metrics.TableQueryMetrics;
import org.apache.cassandra.index.sai.utils.PrimaryKey;
import org.apache.cassandra.net.ParamType;
import org.apache.cassandra.schema.TableMetadata;
@@ -73,7 +72,6 @@ public class QueryController
private final ColumnFamilyStore cfs;
private final ReadCommand command;
private final QueryContext queryContext;
- private final TableQueryMetrics tableQueryMetrics;
private final RowFilter filterOperation;
private final List<DataRange> ranges;
private final AbstractBounds<PartitionPosition> mergeRange;
@@ -85,13 +83,11 @@ public class QueryController
public QueryController(ColumnFamilyStore cfs,
ReadCommand command,
RowFilter filterOperation,
- QueryContext queryContext,
- TableQueryMetrics tableQueryMetrics)
+ QueryContext queryContext)
{
this.cfs = cfs;
this.command = command;
this.queryContext = queryContext;
- this.tableQueryMetrics = tableQueryMetrics;
this.filterOperation = filterOperation;
this.ranges = dataRanges(command);
DataRange first = ranges.get(0);
@@ -249,14 +245,6 @@ public class QueryController
return key.kind() == PrimaryKey.Kind.WIDE &&
!command.clusteringIndexFilter(key.partitionKey()).selects(key.clustering());
}
- /**
- * Used to release all resources and record metrics when query finishes.
- */
- public void finish()
- {
- if (tableQueryMetrics != null) tableQueryMetrics.record(queryContext);
- }
-
// This is an ANN only query
public KeyRangeIterator getTopKRows(RowFilter.Expression expression)
{
diff --git
a/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java
b/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java
index c5976de48f..a61fb18aca 100644
---
a/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java
+++
b/src/java/org/apache/cassandra/index/sai/plan/StorageAttachedIndexSearcher.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -54,12 +55,14 @@ import org.apache.cassandra.index.sai.utils.PrimaryKey;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.utils.AbstractIterator;
+import org.apache.cassandra.utils.Clock;
public class StorageAttachedIndexSearcher implements Index.Searcher
{
private final ReadCommand command;
private final QueryController queryController;
private final QueryContext queryContext;
+ private final TableQueryMetrics tableQueryMetrics;
public StorageAttachedIndexSearcher(ColumnFamilyStore cfs,
TableQueryMetrics tableQueryMetrics,
@@ -69,7 +72,8 @@ public class StorageAttachedIndexSearcher implements
Index.Searcher
{
this.command = command;
this.queryContext = new QueryContext(command, executionQuotaMs);
- this.queryController = new QueryController(cfs, command,
filterOperation, queryContext, tableQueryMetrics);
+ this.queryController = new QueryController(cfs, command,
filterOperation, queryContext);
+ this.tableQueryMetrics = tableQueryMetrics;
}
@Override
@@ -95,10 +99,10 @@ public class StorageAttachedIndexSearcher implements
Index.Searcher
public UnfilteredPartitionIterator search(ReadExecutionController
executionController) throws RequestTimeoutException
{
if (!command.isTopK())
- return new ResultRetriever(queryController, executionController,
queryContext, false);
+ return new ResultRetriever(executionController, false);
else
{
- Supplier<ResultRetriever> resultSupplier = () -> new
ResultRetriever(queryController, executionController, queryContext, true);
+ Supplier<ResultRetriever> resultSupplier = () -> new
ResultRetriever(executionController, true);
// VSTODO performance: if there is shadowed primary keys, we have
to at least query twice.
// First time to find out there are shadow keys, second time to
find out there are no more shadow keys.
@@ -115,7 +119,7 @@ public class StorageAttachedIndexSearcher implements
Index.Searcher
}
}
- private static class ResultRetriever extends
AbstractIterator<UnfilteredRowIterator> implements UnfilteredPartitionIterator
+ private class ResultRetriever extends
AbstractIterator<UnfilteredRowIterator> implements UnfilteredPartitionIterator
{
private final PrimaryKey firstPrimaryKey;
private final PrimaryKey lastPrimaryKey;
@@ -124,26 +128,20 @@ public class StorageAttachedIndexSearcher implements
Index.Searcher
private final KeyRangeIterator resultKeyIterator;
private final FilterTree filterTree;
- private final QueryController queryController;
private final ReadExecutionController executionController;
- private final QueryContext queryContext;
private final PrimaryKey.Factory keyFactory;
private final boolean topK;
private PrimaryKey lastKey;
- private ResultRetriever(QueryController queryController,
- ReadExecutionController executionController,
- QueryContext queryContext,
+ private ResultRetriever(ReadExecutionController executionController,
boolean topK)
{
this.keyRanges = queryController.dataRanges().iterator();
this.currentKeyRange = keyRanges.next().keyRange();
this.resultKeyIterator = Operation.buildIterator(queryController);
this.filterTree = Operation.buildFilter(queryController);
- this.queryController = queryController;
this.executionController = executionController;
- this.queryContext = queryContext;
this.keyFactory = queryController.primaryKeyFactory();
this.firstPrimaryKey = queryController.firstPrimaryKeyInRange();
this.lastPrimaryKey = queryController.lastPrimaryKeyInRange();
@@ -370,13 +368,20 @@ public class StorageAttachedIndexSearcher implements
Index.Searcher
return null;
lastKey = key;
+ long startTimeNanos = Clock.Global.nanoTime();
try (UnfilteredRowIterator partition =
queryController.queryStorage(key, executionController))
{
queryContext.partitionsRead++;
queryContext.checkpoint();
- return applyIndexFilter(key, partition, filterTree,
queryContext);
+ UnfilteredRowIterator filtered = applyIndexFilter(key,
partition, filterTree, queryContext);
+
+ // Note that we record the duration of the read after
post-filtering, which actually
+ // materializes the rows from disk.
+
tableQueryMetrics.postFilteringReadLatency.update(Clock.Global.nanoTime() -
startTimeNanos, TimeUnit.NANOSECONDS);
+
+ return filtered;
}
}
@@ -428,7 +433,7 @@ public class StorageAttachedIndexSearcher implements
Index.Searcher
return new PartitionIterator(partition, staticRow,
Iterators.filter(clusters.iterator(), u -> !((Row)u).isStatic()));
}
- private static class PartitionIterator extends
AbstractUnfilteredRowIterator
+ private class PartitionIterator extends AbstractUnfilteredRowIterator
{
private final Iterator<Unfiltered> rows;
@@ -462,7 +467,7 @@ public class StorageAttachedIndexSearcher implements
Index.Searcher
public void close()
{
FileUtils.closeQuietly(resultKeyIterator);
- queryController.finish();
+ if (tableQueryMetrics != null)
tableQueryMetrics.record(queryContext);
}
}
diff --git
a/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java
b/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java
index e1f1c6933d..846024ebe0 100644
--- a/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/metrics/QueryMetricsTest.java
@@ -38,7 +38,7 @@ public class QueryMetricsTest extends AbstractMetricsTest
public ExpectedException exception = ExpectedException.none();
@Test
- public void testSameIndexNameAcrossKeyspaces() throws Throwable
+ public void testSameIndexNameAcrossKeyspaces()
{
String table = "test_same_index_name_across_keyspaces";
String index = "test_same_index_name_across_keyspaces_index";
@@ -58,7 +58,9 @@ public class QueryMetricsTest extends AbstractMetricsTest
assertEquals(1, rows.all().size());
assertEquals(1L, getTableQueryMetrics(keyspace1, table,
"TotalQueriesCompleted"));
+ assertEquals(1L, getTableQueryMetrics(keyspace1, table,
"PostFilteringReadLatency"));
assertEquals(0L, getTableQueryMetrics(keyspace2, table,
"TotalQueriesCompleted"));
+ assertEquals(0L, getTableQueryMetrics(keyspace2, table,
"PostFilteringReadLatency"));
execute("INSERT INTO " + keyspace2 + '.' + table + " (id1, v1, v2)
VALUES ('0', 0, '0')");
execute("INSERT INTO " + keyspace2 + '.' + table + " (id1, v1, v2)
VALUES ('1', 1, '1')");
@@ -71,6 +73,8 @@ public class QueryMetricsTest extends AbstractMetricsTest
assertEquals(2L, getTableQueryMetrics(keyspace1, table,
"TotalQueriesCompleted"));
assertEquals(1L, getTableQueryMetrics(keyspace2, table,
"TotalQueriesCompleted"));
+ assertEquals(2L, getTableQueryMetrics(keyspace1, table,
"PostFilteringReadLatency"));
+ assertEquals(1L, getTableQueryMetrics(keyspace2, table,
"PostFilteringReadLatency"));
}
@Test
diff --git a/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java
b/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java
index 9e6b0982ac..b2b65454d7 100644
--- a/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/plan/OperationTest.java
@@ -115,22 +115,19 @@ public class OperationTest
controller = new QueryController(BACKEND,
command,
null,
- new QueryContext(command,
DatabaseDescriptor.getRangeRpcTimeout(TimeUnit.MILLISECONDS)),
- null);
+ new QueryContext(command,
DatabaseDescriptor.getRangeRpcTimeout(TimeUnit.MILLISECONDS)));
command =
PartitionRangeReadCommand.allDataRead(CLUSTERING_BACKEND.metadata(),
FBUtilities.nowInSeconds());
controllerClustering = new QueryController(CLUSTERING_BACKEND,
command,
null,
- new QueryContext(command,
DatabaseDescriptor.getRangeRpcTimeout(TimeUnit.MILLISECONDS)),
- null);
+ new QueryContext(command,
DatabaseDescriptor.getRangeRpcTimeout(TimeUnit.MILLISECONDS)));
command =
PartitionRangeReadCommand.allDataRead(STATIC_BACKEND.metadata(),
FBUtilities.nowInSeconds());
controllerStatic = new QueryController(STATIC_BACKEND,
command,
null,
- new QueryContext(command,
DatabaseDescriptor.getRangeRpcTimeout(TimeUnit.MILLISECONDS)),
- null);
+ new QueryContext(command,
DatabaseDescriptor.getRangeRpcTimeout(TimeUnit.MILLISECONDS)));
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]