-
Notifications
You must be signed in to change notification settings - Fork 1.9k
IGNITE-29011 SQL: Add result set size metrics for queries #13517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
88ac13a
281fe67
840fd83
bab6cb3
3daeb0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.apache.ignite.internal.processors.query.calcite.integration; | ||
|
|
||
| import org.apache.ignite.IgniteCache; | ||
| import org.apache.ignite.configuration.CacheConfiguration; | ||
| import org.apache.ignite.configuration.IgniteConfiguration; | ||
| import org.apache.ignite.internal.IgniteEx; | ||
| import org.apache.ignite.internal.processors.metric.MetricRegistryImpl; | ||
| import org.apache.ignite.internal.processors.metric.impl.HistogramMetricImpl; | ||
| import org.apache.ignite.internal.processors.metric.impl.MaxValueMetric; | ||
| import org.junit.Test; | ||
|
|
||
| import static org.apache.ignite.internal.processors.query.running.RunningQueryManager.SQL_USER_QUERIES_REG_NAME; | ||
|
|
||
| /** | ||
| * Tests for result set size histogram and max result set size metrics. | ||
| */ | ||
| public class ResultSetSizeMetricsTest extends AbstractMultiEngineIntegrationTest { | ||
| /** */ | ||
| private static final int FILL_SIZE = 1000; | ||
|
|
||
| /** */ | ||
| @Override protected void afterTest() throws Exception { | ||
| stopAllGrids(); | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { | ||
| IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); | ||
|
|
||
| cfg.setCacheConfiguration(new CacheConfiguration<>(DEFAULT_CACHE_NAME) | ||
| .setIndexedTypes(Integer.class, Integer.class)); | ||
|
|
||
| return cfg; | ||
| } | ||
|
|
||
| /** */ | ||
| @Test | ||
| public void testResultSetSizeMetrics() throws Exception { | ||
| IgniteEx initNode = startGrids(nodeCount()); | ||
|
|
||
| IgniteCache<Integer, Integer> cache = initNode.cache(DEFAULT_CACHE_NAME); | ||
|
|
||
| for (int i = 0; i < FILL_SIZE; i++) | ||
| cache.put(i, i); | ||
|
|
||
| // Execute simple queries with result set sizes: 0, 1, 5, 50, 500. | ||
| for (int limit : new int[] {0, 1, 5, 50, 500}) | ||
| sql(initNode, "SELECT _key FROM \"" + DEFAULT_CACHE_NAME + "\".Integer WHERE _key < ?", limit); | ||
|
|
||
| // Execute queries with aggregation (different reducers on h2) with result set sizes: 10, 100. | ||
| for (int limit : new int[] {10, 100}) | ||
| sql(initNode, "SELECT DISTINCT _key FROM \"" + DEFAULT_CACHE_NAME + "\".Integer WHERE _key < ?", limit); | ||
|
|
||
| // Verify histogram on the initiating node. | ||
| // Bounds: {0, 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000} | ||
| // Bucket 0: x <= 0 -> 1 (size 0) | ||
| // Bucket 1: x <= 1 -> 1 (size 1) | ||
| // Bucket 2: x <= 10 -> 2 (sizes 5, 10) | ||
| // Bucket 3: x <= 100 -> 2 (sizes 50, 100) | ||
| // Bucket 4: x <= 1000 -> 1 (size 500) | ||
| // Buckets 5-8 -> 0 | ||
| long[] values = resultSetSizeHistogram(initNode).value(); | ||
|
|
||
| assertEquals(1, values[0]); | ||
| assertEquals(1, values[1]); | ||
| assertEquals(2, values[2]); | ||
| assertEquals(2, values[3]); | ||
| assertEquals(1, values[4]); | ||
|
|
||
| for (int i = 5; i < values.length; i++) | ||
| assertEquals(0, values[i]); | ||
|
|
||
| // Verify max value on the initiating node. | ||
| assertEquals(500L, resultSetSizeMax(initNode).value()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably it`s better to use constant here just for test clarification ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Constant for range or constant for each value? I think both is redundant. |
||
|
|
||
| // Verify all other server nodes have zero metrics. | ||
| for (int i = 0; i < nodeCount(); i++) { | ||
| IgniteEx node = grid(i); | ||
|
|
||
| if (node == initNode) | ||
| continue; | ||
|
|
||
| long[] nodeVals = resultSetSizeHistogram(node).value(); | ||
|
|
||
| for (long v : nodeVals) | ||
| assertEquals(0, v); | ||
|
|
||
| assertEquals("Expected max value 0 on node [" + node.name() + "]", | ||
| 0L, resultSetSizeMax(node).value()); | ||
| } | ||
| } | ||
|
|
||
| /** */ | ||
| private HistogramMetricImpl resultSetSizeHistogram(IgniteEx ignite) { | ||
| MetricRegistryImpl mreg = ignite.context().metric().registry(SQL_USER_QUERIES_REG_NAME); | ||
|
|
||
| HistogramMetricImpl hist = mreg.findMetric("resultSetSizeHistogram"); | ||
|
|
||
| assertNotNull(hist); | ||
|
|
||
| return hist; | ||
| } | ||
|
|
||
| /** */ | ||
| private MaxValueMetric resultSetSizeMax(IgniteEx ignite) { | ||
| MetricRegistryImpl mreg = ignite.context().metric().registry(SQL_USER_QUERIES_REG_NAME); | ||
|
|
||
| MaxValueMetric max = mreg.findMetric("maxResultSetSize"); | ||
|
|
||
| assertNotNull(max); | ||
|
|
||
| return max; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,7 +47,9 @@ | |
| import org.apache.ignite.internal.processors.closure.GridClosureProcessor; | ||
| import org.apache.ignite.internal.processors.metric.MetricRegistryImpl; | ||
| import org.apache.ignite.internal.processors.metric.impl.AtomicLongMetric; | ||
| import org.apache.ignite.internal.processors.metric.impl.HistogramMetricImpl; | ||
| import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric; | ||
| import org.apache.ignite.internal.processors.metric.impl.MaxValueMetric; | ||
| import org.apache.ignite.internal.processors.query.GridQueryCancel; | ||
| import org.apache.ignite.internal.processors.query.GridQueryFinishedInfo; | ||
| import org.apache.ignite.internal.processors.query.GridQueryStartedInfo; | ||
|
|
@@ -141,6 +143,12 @@ public class RunningQueryManager { | |
| */ | ||
| private final AtomicLongMetric canceledQrsCnt; | ||
|
|
||
| /** Histogram of result set sizes for SQL queries. */ | ||
| private final HistogramMetricImpl resultSetSizeHistogram; | ||
|
|
||
| /** Maximum result set size for SQL queries. */ | ||
| private final MaxValueMetric maxResultSetSize; | ||
|
|
||
| /** Kernal context. */ | ||
| private final GridKernalContext ctx; | ||
|
|
||
|
|
@@ -231,6 +239,13 @@ public RunningQueryManager(GridKernalContext ctx) { | |
|
|
||
| canceledQrsCnt = userMetrics.longMetric("canceled", "Number of canceled queries that have been started " + | ||
| "on this node. This metric number included in the general 'failed' metric."); | ||
|
|
||
| resultSetSizeHistogram = userMetrics.histogram("resultSetSizeHistogram", | ||
| new long[] {0, 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000}, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we also give a Billion here ? In distributed huge cluster it`s normal i think
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fetching more than million entries for sql query it's not normal even if cluster contains billions (I think it's even not ok to fetch more than 1000 entries). |
||
| "Histogram of result set sizes for SQL queries."); | ||
|
|
||
| maxResultSetSize = userMetrics.maxValueMetric("maxResultSetSize", | ||
| "Maximum result set size for SQL queries.", 60_000L, 5); | ||
| } | ||
|
|
||
| /** */ | ||
|
|
@@ -269,6 +284,16 @@ public void start(GridSpinBusyLock busyLock) { | |
| }, EventType.EVT_NODE_FAILED, EventType.EVT_NODE_LEFT); | ||
| } | ||
|
|
||
| /** | ||
| * Called when a result set is fully fetched. Increments result set size metrics. | ||
| * | ||
| * @param size Result set size (number of fetched rows). | ||
| */ | ||
| public void onFullyFetched(long size) { | ||
| resultSetSizeHistogram.value(size); | ||
| maxResultSetSize.update(size); | ||
| } | ||
|
|
||
| /** | ||
| * Registers running query and returns an id associated with the query. | ||
| * | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1400,4 +1400,9 @@ private List<GridCacheSqlQuery> prepareMapQueryForSinglePartition(GridCacheTwoSt | |
|
|
||
| return Collections.singletonList(originalQry); | ||
| } | ||
|
|
||
| /** */ | ||
| IgniteH2Indexing h2() { | ||
| return h2; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we need 'whole' IgniteH2Indexing access here ? I think better give only necessary i.e. : return h2.runningQueryManager();
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But it looks not very consistent, runing query manager is not relied to reduce executor, but reduce executor is a part of indexing, so it's more correct to bind these two components. |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see SqlDiagnosticIntegrationTest probably it about diagnostic too ? I don`t know here ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SqlDiagnosticIntegrationTest - is about Calcite only engine. The new test uses both engines.