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 <calebrackli...@gmail.com>
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: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to