diff --git a/ebean-api/src/main/java/io/ebean/meta/QueryPlanRequest.java b/ebean-api/src/main/java/io/ebean/meta/QueryPlanRequest.java
index 3510b30cc..c4a69b1aa 100644
--- a/ebean-api/src/main/java/io/ebean/meta/QueryPlanRequest.java
+++ b/ebean-api/src/main/java/io/ebean/meta/QueryPlanRequest.java
@@ -41,6 +41,9 @@ public class QueryPlanRequest {
/**
* Set the maximum number of plans to capture.
+ *
+ * Use this to limit how much query plan capturing is done as query
+ * plan capture is actual database load.
*/
public void setMaxCount(int maxCount) {
this.maxCount = maxCount;
@@ -58,7 +61,9 @@ public class QueryPlanRequest {
/**
* Set the maximum amount of time we want to use to capture plans.
*
- * Query plan collection will stop once this time is exceeded.
+ * Query plan collection will stop once this time is exceeded. We use
+ * this to ensure the query plan capture does not use excessive amount
+ * of time - put too much load on the database.
*/
public void setMaxTimeMillis(long maxTimeMillis) {
this.maxTimeMillis = maxTimeMillis;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/NoopQueryPlanManager.java b/ebean-core/src/main/java/io/ebeaninternal/api/NoopQueryPlanManager.java
index e00ad57f1..813121f92 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/api/NoopQueryPlanManager.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/api/NoopQueryPlanManager.java
@@ -8,6 +8,11 @@ import java.util.List;
class NoopQueryPlanManager implements QueryPlanManager {
+ @Override
+ public void setDefaultThreshold(long thresholdMicros) {
+ // do nothing
+ }
+
@Override
public SpiQueryBindCapture createBindCapture(SpiQueryPlan queryPlan) {
return SpiQueryBindCapture.NOOP;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/QueryPlanManager.java b/ebean-core/src/main/java/io/ebeaninternal/api/QueryPlanManager.java
index f9750c47a..da7ce2b43 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/api/QueryPlanManager.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/api/QueryPlanManager.java
@@ -12,6 +12,11 @@ public interface QueryPlanManager {
QueryPlanManager NOOP = new NoopQueryPlanManager();
+ /**
+ * Update the global default threshold used when new query plans are created.
+ */
+ void setDefaultThreshold(long thresholdMicros);
+
/**
* Create the bind capture for the given query plan.
*/
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
index 5e8db9c1c..0e4d22768 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
@@ -2329,6 +2329,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
List queryPlanInit(QueryPlanInit initRequest) {
+ if (initRequest.isAll()) {
+ queryPlanManager.setDefaultThreshold(initRequest.getThresholdMicros());
+ }
return beanDescriptorManager.queryPlanInit(initRequest);
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanManager.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanManager.java
index c2e6aa358..4ff62f44d 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanManager.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanManager.java
@@ -30,14 +30,14 @@ public class CQueryPlanManager implements QueryPlanManager {
private final TransactionManager transactionManager;
- private final long defaultThreshold;
-
private final QueryPlanLogger planLogger;
private final TimedMetric timeCollection;
private final TimedMetric timeBindCapture;
+ private long defaultThreshold;
+
public CQueryPlanManager(TransactionManager transactionManager, long defaultThreshold, QueryPlanLogger planLogger, ExtraMetrics extraMetrics) {
this.transactionManager = transactionManager;
this.defaultThreshold = defaultThreshold;
@@ -46,6 +46,11 @@ public class CQueryPlanManager implements QueryPlanManager {
this.timeBindCapture = extraMetrics.getBindCapture();
}
+ @Override
+ public void setDefaultThreshold(long thresholdMicros) {
+ this.defaultThreshold = thresholdMicros;
+ }
+
@Override
public SpiQueryBindCapture createBindCapture(SpiQueryPlan queryPlan) {
return new CQueryBindCapture(this, queryPlan, defaultThreshold);
diff --git a/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java b/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java
index 48cc264c6..8446f9d5b 100644
--- a/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java
+++ b/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java
@@ -175,17 +175,24 @@ public class TestCustomerFinder extends BaseTestCase {
ResetBasicData.reset();
+ // change default collect query plan threshold to 200 micros
+ QueryPlanInit init0 = new QueryPlanInit();
+ init0.setAll(true);
+ init0.setThresholdMicros(200);
+ final List plans = server().getMetaInfoManager().queryPlanInit(init0);
+ assertThat(plans.size()).isGreaterThan(1);
+
// the server has some plans
runQueries();
- // enable query plan bind capture on all plans threshold 100 micros
+ // change query plan threshold to 100 micros
QueryPlanInit init = new QueryPlanInit();
init.setAll(true);
init.setThresholdMicros(100);
final List appliedToPlans = server().getMetaInfoManager().queryPlanInit(init);
assertThat(appliedToPlans.size()).isGreaterThan(4);
- // will collect bind captures
+ // run queries again
runQueries();
ServerMetrics metrics = server().getMetaInfoManager().collectMetrics();
@@ -203,12 +210,21 @@ public class TestCustomerFinder extends BaseTestCase {
// obtains db query plans ...
QueryPlanRequest request = new QueryPlanRequest();
- List plans = server().getMetaInfoManager().queryPlanCollectNow(request);
- assertThat(plans).isNotEmpty();
+ // collect max 1000 plans (use something more like 10)
+ request.setMaxCount(1_000);
+ // don't collect any more plans if used 10 secs
+ request.setMaxTimeMillis(10_000);
+ List plans0 = server().getMetaInfoManager().queryPlanCollectNow(request);
+ assertThat(plans0).isNotEmpty();
for (MetaQueryPlan plan : plans) {
+ logger.info("queryplan label:{}, queryTimeMicros:{} loc:{} sql:{} bind:{} plan:{}",
+ plan.getLabel(), plan.getQueryTimeMicros(), plan.getProfileLocation(),
+ plan.getSql(), plan.getBind(), plan.getPlan());
System.out.println(plan);
}
+
+ //DB.getBackgroundExecutor().scheduleWithFixedDelay(...)
}
@Test