diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-11-02 14:38:31 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-11-03 15:36:47 +0100 |
commit | 85bd0e6065d97319657535954d8a97c9ca161430 (patch) | |
tree | fe2513f0ab7f838a7f0886b007eb022a781dbb78 /sonar-db/src/main/java/org/sonar | |
parent | d965fca5ff557a3d2cab134435ce05b8d8ab5df1 (diff) | |
download | sonarqube-85bd0e6065d97319657535954d8a97c9ca161430.tar.gz sonarqube-85bd0e6065d97319657535954d8a97c9ca161430.zip |
SONAR-8325 Improve MeasureDao#selectByQuery performance
It now accepts either a list of projects or a project with a list of components, but no more a list of components of any projects
It's no more possible to query a list of any components, because when doing that the performance are very bad (it would probably requires to add a column PROJECT_MEASURES.PROJECT_UUID)
Diffstat (limited to 'sonar-db/src/main/java/org/sonar')
-rw-r--r-- | sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java | 41 | ||||
-rw-r--r-- | sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java | 113 |
2 files changed, 117 insertions, 37 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java index 0536a8389d6..c298bb18ff1 100644 --- a/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java @@ -41,8 +41,11 @@ public class MeasureDao implements Dao { /** * Selects the measures of either the last analysis (when {@link MeasureQuery#analysisUuid} is {@code null}) or of the - * specified analysis (given by {@link MeasureQuery#analysisUuid}) for the component UUIDs specified in - * {@link MeasureQuery#componentUuids}. + * specified analysis (given by {@link MeasureQuery#analysisUuid}). + * The components can be specified either as : + * - A list of projects in {@link MeasureQuery#projectUuids} + * - A list of components in {@link MeasureQuery#componentUuids} with one mandatory project in {@link MeasureQuery#projectUuids} + * - One single component in {@link MeasureQuery#componentUuids} * <p> * In addition, this method returns measures which are not associated to any developer, unless one is specified in * {@link MeasureQuery#personId}. @@ -56,22 +59,29 @@ public class MeasureDao implements Dao { if (query.returnsEmpty()) { return Collections.emptyList(); } - if (query.getComponentUuids() == null) { - return mapper(dbSession).selectByQuery(query); + if (query.getComponentUuids() != null) { + return executeLargeInputs( + query.getComponentUuids(), + componentUuids -> { + MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfComponentUuids(query, componentUuids); + return mapper(dbSession).selectByQuery(pageQuery); + }); + } else if (query.getProjectUuids() != null) { + return executeLargeInputs( + query.getProjectUuids(), + projectUuids -> { + MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfProjectUuids(query, projectUuids); + return mapper(dbSession).selectByQuery(pageQuery); + }); } - return executeLargeInputs(query.getComponentUuids(), componentUuids -> { - MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfComponentUuids(query, componentUuids); - return mapper(dbSession).selectByQuery(pageQuery); - }); + return mapper(dbSession).selectByQuery(query); } public void selectByQuery(DbSession dbSession, MeasureQuery query, ResultHandler resultHandler) { if (query.returnsEmpty()) { return; } - if (query.getComponentUuids() == null) { - mapper(dbSession).selectByQuery(query, resultHandler); - } else { + if (query.getComponentUuids() != null) { executeLargeInputsWithoutOutput( query.getComponentUuids(), componentUuids -> { @@ -79,7 +89,16 @@ public class MeasureDao implements Dao { mapper(dbSession).selectByQuery(pageQuery, resultHandler); return null; }); + } else if (query.getProjectUuids() != null) { + executeLargeInputsWithoutOutput( + query.getProjectUuids(), + projectUuids -> { + MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfProjectUuids(query, projectUuids); + mapper(dbSession).selectByQuery(pageQuery, resultHandler); + return null; + }); } + mapper(dbSession).selectByQuery(query, resultHandler); } public List<PastMeasureDto> selectPastMeasures(DbSession dbSession, diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java index 80b49427fcc..00b724df175 100644 --- a/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java +++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java @@ -19,39 +19,50 @@ */ package org.sonar.db.measure; -import java.util.Collection; import java.util.List; import java.util.Objects; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkState; -import static java.util.Collections.singleton; +import static com.google.common.base.Preconditions.checkArgument; import static java.util.Collections.singletonList; import static java.util.Objects.requireNonNull; public class MeasureQuery { private final String analysisUuid; + + @CheckForNull + private final List<String> projectUuids; + + @CheckForNull private final List<String> componentUuids; + @CheckForNull - private final Collection<Integer> metricIds; + private final List<Integer> metricIds; + @CheckForNull - private final Collection<String> metricKeys; + private final List<String> metricKeys; + @CheckForNull private final Long personId; private MeasureQuery(Builder builder) { - this(builder.analysisUuid, builder.componentUuids, builder.metricIds, builder.metricKeys, builder.personId); + this(builder.analysisUuid, builder.projectUuids, builder.componentUuids, builder.metricIds, builder.metricKeys, builder.personId); } private MeasureQuery(@Nullable String analysisUuid, - List<String> componentUuids, - @Nullable Collection<Integer> metricIds, - @Nullable Collection<String> metricKeys, + @Nullable List<String> projectUuids, + @Nullable List<String> componentUuids, + @Nullable List<Integer> metricIds, + @Nullable List<String> metricKeys, @Nullable Long personId) { - requireNonNull(componentUuids, "Component UUIDs must be set"); - checkState(metricIds == null || metricKeys == null, "Metric IDs and keys must not be set both"); + checkArgument(metricIds == null || metricKeys == null, "Metric IDs and keys must not be set both"); + checkArgument(projectUuids != null || componentUuids != null, "At least one filter on component UUID is expected"); + checkArgument(componentUuids == null || componentUuids.size() == 1 || (projectUuids != null && projectUuids.size() == 1), + "Component UUIDs can only be used when a single project UUID is set"); + this.analysisUuid = analysisUuid; + this.projectUuids = projectUuids; this.componentUuids = componentUuids; this.metricIds = metricIds; this.metricKeys = metricKeys; @@ -62,17 +73,33 @@ public class MeasureQuery { return analysisUuid; } + @CheckForNull + public List<String> getProjectUuids() { + return projectUuids; + } + + @CheckForNull + public String getProjectUuid() { + return isOnComponents() ? projectUuids.get(0) : null; + } + + @CheckForNull public List<String> getComponentUuids() { return componentUuids; } @CheckForNull - public Collection<Integer> getMetricIds() { + public String getComponentUuid() { + return isOnSingleComponent() ? componentUuids.get(0) : null; + } + + @CheckForNull + public List<Integer> getMetricIds() { return metricIds; } @CheckForNull - public Collection<String> getMetricKeys() { + public List<String> getMetricKeys() { return metricKeys; } @@ -82,11 +109,24 @@ public class MeasureQuery { } public boolean returnsEmpty() { - return componentUuids.isEmpty() + return (projectUuids != null && projectUuids.isEmpty()) + || (componentUuids != null && componentUuids.isEmpty()) || (metricIds != null && metricIds.isEmpty()) || (metricKeys != null && metricKeys.isEmpty()); } + public boolean isOnProjects() { + return projectUuids != null && componentUuids == null; + } + + public boolean isOnComponents() { + return projectUuids != null && projectUuids.size() == 1 && componentUuids != null; + } + + public boolean isOnSingleComponent() { + return projectUuids == null && componentUuids != null && componentUuids.size() == 1; + } + @Override public boolean equals(@Nullable Object o) { if (this == o) { @@ -97,10 +137,11 @@ public class MeasureQuery { } MeasureQuery that = (MeasureQuery) o; return Objects.equals(analysisUuid, that.analysisUuid) && - Objects.equals(componentUuids, that.componentUuids) && - Objects.equals(metricIds, that.metricIds) && - Objects.equals(metricKeys, that.metricKeys) && - Objects.equals(personId, that.personId); + Objects.equals(projectUuids, that.projectUuids) && + Objects.equals(componentUuids, that.componentUuids) && + Objects.equals(metricIds, that.metricIds) && + Objects.equals(metricKeys, that.metricKeys) && + Objects.equals(personId, that.personId); } @Override @@ -112,15 +153,20 @@ public class MeasureQuery { return new Builder(); } + static MeasureQuery copyWithSubsetOfProjectUuids(MeasureQuery query, List<String> projectUuids) { + return new MeasureQuery(query.analysisUuid, projectUuids, query.componentUuids, query.metricIds, query.metricKeys, query.personId); + } + static MeasureQuery copyWithSubsetOfComponentUuids(MeasureQuery query, List<String> componentUuids) { - return new MeasureQuery(query.analysisUuid, componentUuids, query.metricIds, query.metricKeys, query.personId); + return new MeasureQuery(query.analysisUuid, query.projectUuids, componentUuids, query.metricIds, query.metricKeys, query.personId); } public static final class Builder { private String analysisUuid; + private List<String> projectUuids; private List<String> componentUuids; - private Collection<Integer> metricIds; - private Collection<String> metricKeys; + private List<Integer> metricIds; + private List<String> metricKeys; private Long personId; private Builder() { @@ -132,11 +178,26 @@ public class MeasureQuery { return this; } - public Builder setComponentUuids(List<String> componentUuids) { + /** + * List of projects + */ + public Builder setProjectUuids(@Nullable List<String> projectUuids) { + this.projectUuids = projectUuids; + return this; + } + + /** + * List of components of a project + */ + public Builder setComponentUuids(String projectUuid, List<String> componentUuids) { + setProjectUuids(singletonList(requireNonNull(projectUuid))); this.componentUuids = componentUuids; return this; } + /** + * Single component + */ public Builder setComponentUuid(String componentUuid) { this.componentUuids = singletonList(componentUuid); return this; @@ -145,26 +206,26 @@ public class MeasureQuery { /** * All the measures are returned if parameter is {@code null}. */ - public Builder setMetricIds(@Nullable Collection<Integer> metricIds) { + public Builder setMetricIds(@Nullable List<Integer> metricIds) { this.metricIds = metricIds; return this; } public Builder setMetricId(int metricId) { - this.metricIds = singleton(metricId); + this.metricIds = singletonList(metricId); return this; } /** * All the measures are returned if parameter is {@code null}. */ - public Builder setMetricKeys(@Nullable Collection<String> s) { + public Builder setMetricKeys(@Nullable List<String> s) { this.metricKeys = s; return this; } public Builder setMetricKey(String s) { - this.metricKeys = singleton(s); + this.metricKeys = singletonList(s); return this; } |