Skip to content
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

IGNITE-22557 Create system view for SQL query plans history #11425

Open
wants to merge 34 commits into
base: master
Choose a base branch
from

Conversation

oleg-vlsk
Copy link
Contributor

Thank you for submitting the pull request to the Apache Ignite.

In order to streamline the review of the contribution
we ask you to ensure the following steps have been taken:

The Contribution Checklist

  • There is a single JIRA ticket related to the pull request.
  • The web-link to the pull request is attached to the JIRA ticket.
  • The JIRA ticket has the Patch Available state.
  • The pull request body describes changes that have been made.
    The description explains WHAT and WHY was made instead of HOW.
  • The pull request title is treated as the final commit message.
    The following pattern must be used: IGNITE-XXXX Change summary where XXXX - number of JIRA issue.
  • A reviewer has been mentioned through the JIRA comments
    (see the Maintainers list)
  • The pull request has been checked by the Teamcity Bot and
    the green visa attached to the JIRA ticket (see TC.Bot: Check PR)

Notes

If you need any help, please email [email protected] or ask anу advice on http://asf.slack.com #ignite channel.

"; key column index=" + (keyColIdx < 0 ? "N/A" : keyColIdx) +
"; value column index=" + (valColIdx < 0 ? "N/A" : valColIdx) +
"; row count=" + rowsNum +
"; values=" + (rows == null ? "N/A" : "[" + rowsToString(rows) + "]") +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we should add rows to plan. Plan will be different each time and it will wash out all other plan. For me value of DML plans are not clear. Perhaps it will be useful to have only plan for selectQry, but looks like we don't have this plan during update. Perhaps these queries are tracked on map phase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concept of plans for DML commands has been completely changed.

@@ -472,6 +473,17 @@ private void onQueryRequest0(
);
}

SqlPlanHistoryTracker planHistTracker = ctx.query().runningQueryManager().planHistoryTracker();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h2.runningQueryManager().planHistoryTracker().addPlan(...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

@@ -522,6 +523,17 @@ else if (QueryUtils.wasCancelled(err))
);
}

SqlPlanHistoryTracker planHistTracker = ctx.query().runningQueryManager().planHistoryTracker();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h2.runningQueryManager().planHistoryTracker().addPlan(...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

this.schema = schema;
this.loc = loc;

hash = 31 * (31 * plan.hashCode() + qry.hashCode() + schema.hashCode()) + (loc ? 1 : 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Objects.hash(...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Objects.hash() method has been implemented.

private final SqlPlanKey key;

/** */
private final SqlPlanValue val;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need extra SqlPlanValue class? Looks like everithing can be stored in SqlPlan

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All SQL plan history data is now stored in the SqlPlan class; the SqlPlanKey and SqlPlanValue classes have been removed.

if (historySize <= 0)
return;

SqlPlan sqlPlan = new SqlPlan(plan, qry, schema, loc, startTs, engine);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of three entities SqlPlan, SqlPlanKey, SqlPlanValue only one can be used (SqlPlan)
sqlPlanHistory can be just a map from SqlPlan to timestamp and we can add entries like:
sqlPlanHistory.put(sqlPlan.key(), U.currentTimeMillis());
We don't need extra parameter startTs since almost always it will be equals to U.currentTimeMillis().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (see previous comment).

}

/** */
public enum SqlEngine {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The core module shouldn't know about list of query engines. Let's use String instead of this enum. Use IndexingQueryEngineConfiguration.ENGINE_NAME and CalciteQueryEngineConfiguration.ENGINE_NAME from indexing and calcite modules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -80,10 +80,10 @@ public final class UpdatePlan {

/** Number of rows in rows based MERGE or INSERT. */
private final int rowsNum;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant changes (all in this file)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.


SqlPlan sqlPlan = new SqlPlan(plan, qry, schema, loc, engine);

sqlPlanHistory.put(sqlPlan, sqlPlan.startTime());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure key will be updated after this call.
You use information only from key (including startTime) in the view, if key is not updated, than view will contain a wrong startTime field value.

Copy link
Contributor Author

@oleg-vlsk oleg-vlsk Sep 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the key wasn't updated during the put() operation. To fix it, I changed the SQL plan history data structure from GridBoundedConcurrentLinkedHashMap to GridBoundedConcurrentLinkedHashSet and edited the addPlan() method, so that newer entries would replace older ones with the same SQL plan.

* @param historySize History size.
*/
public void setHistorySize(int historySize) {
this.historySize = historySize;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's recreate sqlPlanHistory here. Now this method used only once in test with value 0, but if someone will use this method (perhaps in test too) with another value, result can be unpredicted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

import org.junit.Test;

/** Test for Sql plan history configuration. */
public class SqlPlanHistoryConfigIntegrationTest extends GridCommonAbstractTest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this test to ignite-spring module, instead of adding new dependency to ignite-calcite.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SqlPlanHistoryConfigIntegrationTest has been moved to the ignite-spring module.

* @return Cache configuration.
*/
@SuppressWarnings("unchecked")
private CacheConfiguration configureCahce(String name, Class<?>... idxTypes) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: Cahce

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.


/** Tests for SQL plan history (Calcite engine). */
@RunWith(Parameterized.class)
public class SqlPlanHistoryIntegrationTest extends GridCommonAbstractTest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test already Parameterized. Perhaps it's worth to add parameters queryEngine and clientMode instead of creating child classes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queryEngine and clientMode have been added to the list of parameters. Test subclasses for H2 and clients have been removed.

Comment on lines 276 to 278
queryNode().context().query().runningQueryManager().resetPlanHistoryMetrics();

mapNode().context().query().runningQueryManager().resetPlanHistoryMetrics();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for (IgniteEx ignite: G.allGrids())
    ignite.context().query().runningQueryManager().resetPlanHistoryMetrics();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

/** Checks successful JDBC queries. */
@Test
public void testJdbcQuery() throws SQLException {
if (loc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To ignore test it's better to use assumeTrue/assumeFalse statements. In your case assumeFalse(loc).
Tests will be marked as ignored instead of passed (and we can also provide a reason, why they are ignored).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SqlPlanHistoryIntegrationTest has been refactored using the assumeFalse statements.

@alex-plekhanov
Copy link
Contributor

Please resolve also merge conflicts

CdcConfigurationTest.class
CdcConfigurationTest.class,

SqlPlanHistoryConfigTest.class
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add comma at the end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comma added.

oleg-vlsk and others added 25 commits October 8, 2024 07:17
…g#executeUpdate0 to IgniteH2Indexing#executeUpdate
…dConcurrentLinkedHashSet, SqlPlanHistoryTracker#addPlan changed, SqlPlanHistoryIntegrationTest#testEntryReplacement added
…HistoryIntegrationTest refactored with assumeFalse(), SqlPlanHistoryTracker#setHistorySize edited
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants