Skip to content

Commit ffa84a5

Browse files
pkolaczkadelapena
authored andcommitted
Update src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
Co-authored-by: Andrés de la Peña <[email protected]>
1 parent 8acd7f5 commit ffa84a5

File tree

5 files changed

+207
-95
lines changed

5 files changed

+207
-95
lines changed

src/java/org/apache/cassandra/index/sai/QueryContext.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public void updateAnnRerankFloor(float observedFloor)
246246
annRerankFloor = max(annRerankFloor, observedFloor);
247247
}
248248

249-
public void recordQueryPlan(Plan.RowsIteration originalPlan, Plan.RowsIteration.RowsIteration optimizedPlan)
249+
public void recordQueryPlan(Plan.RowsIteration originalPlan, Plan.RowsIteration optimizedPlan)
250250
{
251251
if (CassandraRelevantProperties.SAI_QUERY_PLAN_METRICS_ENABLED.getBoolean())
252252
this.queryPlanInfo = new PlanInfo(originalPlan, optimizedPlan);
@@ -342,22 +342,22 @@ public static class PlanInfo
342342
public final boolean searchExecutedBeforeOrder;
343343
public final boolean filterExecutedAfterOrderedScan;
344344

345-
public final double rowsToReturnEstimated;
346-
public final double rowsToFetchEstimated;
347-
public final double keysToIterateEstimated;
348-
public final double selectivityEstimated;
349-
public final double costEstimated;
345+
public final long costEstimated;
346+
public final long rowsToReturnEstimated;
347+
public final long rowsToFetchEstimated;
348+
public final long keysToIterateEstimated;
349+
public final int logSelectivityEstimated;
350350

351351
public final int indexReferencesInQuery;
352352
public final int indexReferencesInPlan;
353353

354354
public PlanInfo(@Nonnull Plan.RowsIteration originalPlan, @Nonnull Plan.RowsIteration optimizedPlan)
355355
{
356-
this.costEstimated = optimizedPlan.fullCost();
357-
this.rowsToReturnEstimated = optimizedPlan.expectedRows();
358-
this.rowsToFetchEstimated = optimizedPlan.estimatedRowsToFetch();
359-
this.keysToIterateEstimated = optimizedPlan.estimatedKeysToIterate();
360-
this.selectivityEstimated = optimizedPlan.selectivity();
356+
this.costEstimated = Math.round(optimizedPlan.fullCost());
357+
this.rowsToReturnEstimated = Math.round(optimizedPlan.expectedRows());
358+
this.rowsToFetchEstimated = Math.round(optimizedPlan.estimatedRowsToFetch());
359+
this.keysToIterateEstimated = Math.round(optimizedPlan.estimatedKeysToIterate());
360+
this.logSelectivityEstimated = Math.min(20, (int) Math.floor(-Math.log10(optimizedPlan.selectivity())));
361361
this.indexReferencesInQuery = originalPlan.referencedIndexCount();
362362
this.indexReferencesInPlan = optimizedPlan.referencedIndexCount();
363363
this.searchExecutedBeforeOrder = optimizedPlan.isSearchThenOrderHybrid();

src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java

Lines changed: 107 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.function.Predicate;
2323
import java.util.regex.Pattern;
2424

25+
import javax.annotation.Nullable;
26+
2527
import com.codahale.metrics.Counter;
2628
import com.codahale.metrics.Histogram;
2729
import com.codahale.metrics.Timer;
@@ -199,13 +201,8 @@ public static class PerTable extends AbstractQueryMetrics
199201
public final Counter totalRowTombstonesFetched;
200202
public final Counter totalQueriesCompleted;
201203

202-
public final Counter totalRowsToReturnEstimated;
203-
public final Counter totalRowsToFetchEstimated;
204-
public final Counter totalKeysToIterateEstimated;
205-
public final Counter totalCostEstimated;
206-
207-
public final Counter sortThenFilterQueriesCompleted;
208-
public final Counter filterThenSortQueriesCompleted;
204+
@Nullable
205+
public final QueryPlanMetrics queryPlanMetrics;
209206

210207
/**
211208
* @param table the table to measure metrics for
@@ -225,13 +222,9 @@ public PerTable(TableMetadata table, QueryKind queryKind, Predicate<ReadCommand>
225222
totalRowTombstonesFetched = Metrics.counter(createMetricName("TotalRowTombstonesFetched"));
226223
totalQueriesCompleted = Metrics.counter(createMetricName("TotalQueriesCompleted"));
227224
totalQueryTimeouts = Metrics.counter(createMetricName("TotalQueryTimeouts"));
228-
totalRowsToReturnEstimated = Metrics.counter(createMetricName("TotalRowsToReturnEstimated"));
229-
totalRowsToFetchEstimated = Metrics.counter(createMetricName("TotalRowsToFetchEstimated"));
230-
totalKeysToIterateEstimated = Metrics.counter(createMetricName("TotalKeysToIterateEstimated"));
231-
totalCostEstimated = Metrics.counter(createMetricName("TotalCostEstimated"));
232-
233-
sortThenFilterQueriesCompleted = Metrics.counter(createMetricName("SortThenFilterQueriesCompleted"));
234-
filterThenSortQueriesCompleted = Metrics.counter(createMetricName("FilterThenSortQueriesCompleted"));
225+
queryPlanMetrics = (CassandraRelevantProperties.SAI_QUERY_PLAN_METRICS_ENABLED.getBoolean())
226+
? new QueryPlanMetrics()
227+
: null;
235228
}
236229

237230
@Override
@@ -253,17 +246,40 @@ public void record(QueryContext.Snapshot snapshot)
253246
totalRowTombstonesFetched.inc(snapshot.rowTombstonesFetched);
254247

255248
QueryContext.PlanInfo queryPlanInfo = snapshot.queryPlanInfo;
256-
if (queryPlanInfo != null)
249+
if (queryPlanInfo != null && queryPlanMetrics != null)
257250
{
258-
totalCostEstimated.inc(Math.round(queryPlanInfo.costEstimated));
259-
totalRowsToReturnEstimated.inc(Math.round(queryPlanInfo.rowsToReturnEstimated));
260-
totalRowsToFetchEstimated.inc(Math.round(queryPlanInfo.rowsToFetchEstimated));
261-
totalKeysToIterateEstimated.inc(Math.round(queryPlanInfo.keysToIterateEstimated));
251+
queryPlanMetrics.totalCostEstimated.inc(queryPlanInfo.costEstimated);
252+
queryPlanMetrics.totalRowsToReturnEstimated.inc(queryPlanInfo.rowsToReturnEstimated);
253+
queryPlanMetrics.totalRowsToFetchEstimated.inc(queryPlanInfo.rowsToFetchEstimated);
254+
queryPlanMetrics.totalKeysToIterateEstimated.inc(queryPlanInfo.keysToIterateEstimated);
262255

263256
if (queryPlanInfo.filterExecutedAfterOrderedScan)
264-
sortThenFilterQueriesCompleted.inc();
257+
queryPlanMetrics.sortThenFilterQueriesCompleted.inc();
265258
if (queryPlanInfo.searchExecutedBeforeOrder)
266-
filterThenSortQueriesCompleted.inc();
259+
queryPlanMetrics.filterThenSortQueriesCompleted.inc();
260+
}
261+
}
262+
263+
public class QueryPlanMetrics
264+
{
265+
public final Counter totalRowsToReturnEstimated;
266+
public final Counter totalRowsToFetchEstimated;
267+
public final Counter totalKeysToIterateEstimated;
268+
public final Counter totalCostEstimated;
269+
270+
public final Counter sortThenFilterQueriesCompleted;
271+
public final Counter filterThenSortQueriesCompleted;
272+
273+
274+
public QueryPlanMetrics()
275+
{
276+
totalRowsToReturnEstimated = Metrics.counter(createMetricName("TotalRowsToReturnEstimated"));
277+
totalRowsToFetchEstimated = Metrics.counter(createMetricName("TotalRowsToFetchEstimated"));
278+
totalKeysToIterateEstimated = Metrics.counter(createMetricName("TotalKeysToIterateEstimated"));
279+
totalCostEstimated = Metrics.counter(createMetricName("TotalCostEstimated"));
280+
281+
sortThenFilterQueriesCompleted = Metrics.counter(createMetricName("SortThenFilterQueriesCompleted"));
282+
filterThenSortQueriesCompleted = Metrics.counter(createMetricName("FilterThenSortQueriesCompleted"));
267283
}
268284
}
269285
}
@@ -311,33 +327,8 @@ public static class PerQuery extends AbstractQueryMetrics
311327
*/
312328
public final Timer annGraphSearchLatency;
313329

314-
/** Query execution cost as estimated by the planner */
315-
public final Histogram costEstimated;
316-
317-
/** Number of rows to be returned from the query as estimated by the planner */
318-
public final Histogram rowsToReturnEstimated;
319-
320-
/** Number of rows to be fetched by the query as estimated by the planner */
321-
public final Histogram rowsToFetchEstimated;
322-
323-
/** Number of rows to be fetched by the query as estimated by the planner */
324-
public final Histogram keysToIterateEstimated;
325-
326-
/**
327-
* Negative deceimal logarithm of selectivity of the query, before applying the LIMIT clause.
328-
* We use logarithm because selectivity values can be very small (e.g. 10^-9).
329-
*/
330-
public final Histogram logSelectivityEstimated;
331-
332-
/**
333-
* Number of indexes referenced by the optimized query plan.
334-
* The same index referenced from unrelated query clauses,
335-
* leading to separate index searches, are counted separately.
336-
*/
337-
public final Histogram indexReferencesInPlan;
338-
339-
/** Number of indexes referenced by the original query plan before optimization (as stated in the query text) */
340-
public final Histogram indexReferencesInQuery;
330+
@Nullable
331+
public final QueryPlanMetrics queryPlanMetrics;
341332

342333
/**
343334
* @param table the table to measure metrics for
@@ -370,13 +361,9 @@ public PerQuery(TableMetadata table, QueryKind queryKind, Predicate<ReadCommand>
370361
// Key vector metrics that translate to performance
371362
annGraphSearchLatency = Metrics.timer(createMetricName("ANNGraphSearchLatency"));
372363

373-
costEstimated = Metrics.histogram(createMetricName("CostEstimated"), false);
374-
rowsToReturnEstimated = Metrics.histogram(createMetricName("RowsToReturnEstimated"), true);
375-
rowsToFetchEstimated = Metrics.histogram(createMetricName("RowsToFetchEstimated"), true);
376-
keysToIterateEstimated = Metrics.histogram(createMetricName("KeysToIterateEstimated"), true);
377-
logSelectivityEstimated = Metrics.histogram(createMetricName("LogSelectivityEstimated"), true);
378-
indexReferencesInPlan = Metrics.histogram(createMetricName("IndexReferencesInPlan"), true);
379-
indexReferencesInQuery = Metrics.histogram(createMetricName("IndexReferencesInQuery"), false);
364+
queryPlanMetrics = CassandraRelevantProperties.SAI_QUERY_PLAN_METRICS_ENABLED.getBoolean()
365+
? new QueryPlanMetrics()
366+
: null;
380367
}
381368

382369
@Override
@@ -418,17 +405,73 @@ public void record(QueryContext.Snapshot snapshot)
418405
}
419406

420407
QueryContext.PlanInfo queryPlanInfo = snapshot.queryPlanInfo;
421-
if (queryPlanInfo != null)
408+
if (queryPlanInfo != null && queryPlanMetrics != null)
422409
{
423-
costEstimated.update(Math.round(queryPlanInfo.costEstimated));
424-
rowsToReturnEstimated.update(Math.round(queryPlanInfo.rowsToReturnEstimated));
425-
rowsToFetchEstimated.update(Math.round(queryPlanInfo.rowsToFetchEstimated));
426-
keysToIterateEstimated.update(Math.round(queryPlanInfo.keysToIterateEstimated));
427-
double logSelectivity = -Math.log10(queryPlanInfo.selectivityEstimated);
428-
logSelectivityEstimated.update((int) (Math.min(20, Math.floor(logSelectivity))));
429-
indexReferencesInQuery.update(queryPlanInfo.indexReferencesInQuery);
430-
indexReferencesInPlan.update(queryPlanInfo.indexReferencesInPlan);
410+
queryPlanMetrics.costEstimated.update(queryPlanInfo.costEstimated);
411+
queryPlanMetrics.rowsToReturnEstimated.update(queryPlanInfo.rowsToReturnEstimated);
412+
queryPlanMetrics.rowsToFetchEstimated.update(queryPlanInfo.rowsToFetchEstimated);
413+
queryPlanMetrics.keysToIterateEstimated.update(queryPlanInfo.keysToIterateEstimated);
414+
queryPlanMetrics.logSelectivityEstimated.update(queryPlanInfo.logSelectivityEstimated);
415+
queryPlanMetrics.indexReferencesInQuery.update(queryPlanInfo.indexReferencesInQuery);
416+
queryPlanMetrics.indexReferencesInPlan.update(queryPlanInfo.indexReferencesInPlan);
431417
}
432418
}
419+
420+
/// Metrics related to query planning.
421+
/// Moved to separate class so they can be enabled/disabled as a group.
422+
public class QueryPlanMetrics
423+
{
424+
/**
425+
* Query execution cost as estimated by the planner
426+
*/
427+
public final Histogram costEstimated;
428+
429+
/**
430+
* Number of rows to be returned from the query as estimated by the planner
431+
*/
432+
public final Histogram rowsToReturnEstimated;
433+
434+
/**
435+
* Number of rows to be fetched by the query as estimated by the planner
436+
*/
437+
public final Histogram rowsToFetchEstimated;
438+
439+
/**
440+
* Number of keys to be iterated by the query as estimated by the planner
441+
*/
442+
public final Histogram keysToIterateEstimated;
443+
444+
/**
445+
* Negative decimal logarithm of selectivity of the query, before applying the LIMIT clause.
446+
* We use logarithm because selectivity values can be very small (e.g. 10^-9).
447+
*/
448+
public final Histogram logSelectivityEstimated;
449+
450+
/**
451+
* Number of indexes referenced by the optimized query plan.
452+
* The same index referenced from unrelated query clauses,
453+
* leading to separate index searches, are counted separately.
454+
*/
455+
public final Histogram indexReferencesInPlan;
456+
457+
/**
458+
* Number of indexes referenced by the original query plan before optimization (as stated in the query text)
459+
*/
460+
public final Histogram indexReferencesInQuery;
461+
462+
QueryPlanMetrics()
463+
{
464+
costEstimated = Metrics.histogram(createMetricName("CostEstimated"), false);
465+
rowsToReturnEstimated = Metrics.histogram(createMetricName("RowsToReturnEstimated"), true);
466+
rowsToFetchEstimated = Metrics.histogram(createMetricName("RowsToFetchEstimated"), true);
467+
keysToIterateEstimated = Metrics.histogram(createMetricName("KeysToIterateEstimated"), true);
468+
logSelectivityEstimated = Metrics.histogram(createMetricName("LogSelectivityEstimated"), true);
469+
indexReferencesInPlan = Metrics.histogram(createMetricName("IndexReferencesInPlan"), true);
470+
indexReferencesInQuery = Metrics.histogram(createMetricName("IndexReferencesInQuery"), false);
471+
}
472+
}
473+
433474
}
475+
476+
434477
}

src/java/org/apache/cassandra/index/sai/plan/Plan.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ public final double selectivity()
531531

532532
/**
533533
* Returns the number of indexes referenced by this plan.
534+
* The same index referenced from unrelated query clauses,
535+
* leading to separate index searches, are counted separately.
534536
*/
535537
public final int referencedIndexCount()
536538
{
@@ -1757,7 +1759,7 @@ protected Fetch withAccess(Access access)
17571759
* In order to return one row in the result set it may need to retrieve many rows from the source node.
17581760
* Hence, it will typically have higher cost-per-row than the source node, and will return fewer rows.
17591761
*/
1760-
public static class Filter extends RowsIteration
1762+
static class Filter extends RowsIteration
17611763
{
17621764
private final RowFilter filter;
17631765
private final LazyTransform<RowsIteration> source;

test/unit/org/apache/cassandra/index/sai/metrics/AbstractMetricsTest.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
import java.util.concurrent.TimeUnit;
2121
import javax.management.ObjectName;
2222

23+
import org.junit.After;
2324
import org.junit.Before;
2425
import org.junit.Ignore;
2526

27+
import org.apache.cassandra.config.CassandraRelevantProperties;
2628
import org.apache.cassandra.index.sai.SAITester;
2729
import org.apache.cassandra.utils.Throwables;
2830

@@ -32,6 +34,11 @@
3234
@Ignore
3335
public abstract class AbstractMetricsTest extends SAITester
3436
{
37+
boolean indexMetricsEnabled;
38+
boolean perQueryKindPerTableMetricsEnabled;
39+
boolean perQueryKindPerQueryMetricsEnabled;
40+
boolean queryPlanMetricsEnabled;
41+
3542
@Before
3643
public void initializeTest() throws Throwable
3744
{
@@ -40,6 +47,20 @@ public void initializeTest() throws Throwable
4047
startJMXServer();
4148

4249
createMBeanServerConnection();
50+
51+
indexMetricsEnabled = CassandraRelevantProperties.SAI_INDEX_METRICS_ENABLED.getBoolean();
52+
perQueryKindPerQueryMetricsEnabled = CassandraRelevantProperties.SAI_QUERY_KIND_PER_QUERY_METRICS_ENABLED.getBoolean();
53+
perQueryKindPerTableMetricsEnabled = CassandraRelevantProperties.SAI_QUERY_KIND_PER_TABLE_METRICS_ENABLED.getBoolean();
54+
queryPlanMetricsEnabled = CassandraRelevantProperties.SAI_QUERY_PLAN_METRICS_ENABLED.getBoolean();
55+
}
56+
57+
@After
58+
public void cleanupTest() throws Throwable
59+
{
60+
CassandraRelevantProperties.SAI_INDEX_METRICS_ENABLED.setBoolean(indexMetricsEnabled);
61+
CassandraRelevantProperties.SAI_QUERY_KIND_PER_TABLE_METRICS_ENABLED.setBoolean(perQueryKindPerTableMetricsEnabled);
62+
CassandraRelevantProperties.SAI_QUERY_KIND_PER_QUERY_METRICS_ENABLED.setBoolean(perQueryKindPerQueryMetricsEnabled);
63+
CassandraRelevantProperties.SAI_QUERY_PLAN_METRICS_ENABLED.setBoolean(indexMetricsEnabled);
4364
}
4465

4566
protected void waitForIndexCompaction(String keyspace, String table, String index)
@@ -85,7 +106,6 @@ protected void waitForHistogramMeanBetween(ObjectName name, double min, double m
85106
}, 10, TimeUnit.SECONDS);
86107
}
87108

88-
89109
protected void waitForGreaterThanZero(ObjectName name)
90110
{
91111
waitForAssert(() -> {

0 commit comments

Comments
 (0)