Skip to content

Commit

Permalink
IGNITE-24385 Move the planWithoutScanCount method from SqlPlanHistory…
Browse files Browse the repository at this point in the history
…Tracker to H2QueryInfo
  • Loading branch information
oleg-vlsk committed Feb 7, 2025
1 parent 6bbf5df commit 1fe9264
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void addPlan(String plan, String qry, String schema, boolean loc, String
if (sqlPlanHistory == EMPTY_MAP)
return;

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

sqlPlanHistory.put(sqlPlan, U.currentTimeMillis());
}
Expand All @@ -69,23 +69,4 @@ public boolean enabled() {
public void setHistorySize(int histSize) {
sqlPlanHistory = (histSize > 0) ? new GridBoundedConcurrentLinkedHashMap<>(histSize) : Collections.emptyMap();
}

/**
* @param plan SQL plan.
*
* @return SQL plan without the scanCount suffix.
*/
public String planWithoutScanCount(String plan) {
String res = null;

int start = plan.indexOf("\n /* scanCount");

if (start != -1) {
int end = plan.indexOf("*/", start);

res = plan.substring(0, start) + plan.substring(end + 2);
}

return (res == null) ? plan : res;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public long queryId() {
/** */
public synchronized String plan() {
if (plan == null)
plan = stmt.getPlanSQL();
plan = planWithoutScanCount(stmt.getPlanSQL());

return plan;
}
Expand Down Expand Up @@ -209,6 +209,43 @@ public boolean isSuspended() {
return isSuspended;
}

/**
* If the same SQL query is executed sequentially within a single instance of {@link H2Connection} (which happens,
* for example, during consecutive local query executions), the next execution plan is generated using
* a {@link PreparedStatement} stored in the statement cache of this connection — H2Connection#statementCache.<br>
* <br>
* During the preparation of a PreparedStatement, a TableFilter object is created, where the variable scanCount
* stores the number of elements scanned within the query. If this value is not zero, the generated execution plan
* will contain a substring in the following format: "scanCount: X", where X is the value of the scanCount
* variable at the time of plan generation.<br>
* <br>
* The scanCount variable is reset in the TableFilter#startQuery method. However, since execution plans are
* generated and recorded asynchronously, there is no guarantee that plan generation happens immediately after
* TableFilter#startQuery is called.<br>
* <br>
* As a result, identical execution plans differing only by the scanCount suffix may be recorded in the SQL plan
* history. To prevent this, the suffix should be removed from the plan as soon as it is generated with the
* Prepared#getPlanSQL method.<br>
* <br>
*
* @param plan SQL plan.
*
* @return SQL plan without the scanCount suffix.
*/
public String planWithoutScanCount(String plan) {
String res = null;

int start = plan.indexOf("\n /* scanCount");

if (start != -1) {
int end = plan.indexOf("*/", start);

res = plan.substring(0, start) + plan.substring(end + 2);
}

return (res == null) ? plan : res;
}

/**
* Query type.
*/
Expand Down

0 comments on commit 1fe9264

Please sign in to comment.