Merge "Avoid multiple inner joins if dimensions specified"

This commit is contained in:
Jenkins 2015-10-23 14:01:35 +00:00 committed by Gerrit Code Review
commit c47154d279
5 changed files with 56 additions and 73 deletions

View File

@ -1,11 +1,11 @@
/*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
*
*
* Licensed 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
@ -55,12 +55,12 @@ public class MeasurementVerticaRepoImpl implements MeasurementRepo {
"select def.name, mes.definition_dimensions_id, defdims.dimension_set_id, defdims.definition_id, "
+ "mes.time_stamp, mes.value, mes.value_meta "
+ "from MonMetrics.Measurements mes, MonMetrics.Definitions def, MonMetrics.DefinitionDimensions defdims "
+ "%s "
+ "where mes.definition_dimensions_id = defdims.id "
+ "and def.id = defdims.definition_id "
+ "and def.tenant_id = :tenantId "
+ "and mes.time_stamp >= :startTime "
+ "%s "
+ "%s " // metric name here
+ "%s " // dimension and clause here
+ "order by mes.time_stamp ASC "
+ "limit :limit";
@ -114,8 +114,8 @@ public class MeasurementVerticaRepoImpl implements MeasurementRepo {
String sql =
String.format(FIND_BY_METRIC_DEF_SQL,
MetricQueries.buildJoinClauseFor(dimensions, TABLE_TO_JOIN_DIMENSIONS_ON),
sb);
sb,
MetricQueries.buildDimensionAndClause(dimensions, TABLE_TO_JOIN_DIMENSIONS_ON));
Query<Map<String, Object>> query =
h.createQuery(sql)

View File

@ -1,11 +1,11 @@
/*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
*
*
* Licensed 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
@ -48,37 +48,28 @@ public class MetricDefinitionVerticaRepoImpl implements MetricDefinitionRepo {
+ "FROM MonMetrics.Definitions def, MonMetrics.DefinitionDimensions defDims "
// Outer join needed in case there are no dimensions for a definition.
+ "LEFT OUTER JOIN MonMetrics.Dimensions dims ON dims.dimension_set_id = defDims"
+ ".dimension_set_id "
+ "WHERE def.id = defDims.definition_id "
+ "AND defDims.id IN (%s) "
+ "ORDER BY defDims.id ASC ";
private static final String
METRIC_DEFINITIONS_SUB_SELECT =
"SELECT defDimsSub.id "
+ "FROM MonMetrics.Definitions defSub, MonMetrics.DefinitionDimensions defDimsSub"
+ "%s " // Dimensions inner join goes here if dimensions specified.
+ "WHERE defDimsSub.definition_id = defSub.id "
+ "AND defSub.tenant_id = :tenantId "
+ ".dimension_set_id WHERE def.id = defDims.definition_id "
+ "and def.tenant_id = :tenantId "
+ "%s " // Name goes here.
+ "%s " // Offset goes here.
+ "ORDER BY defdimsSub.id ASC %s"; // Limit goes here.
+ "%s " // Dimensions and clause goes here
+ "ORDER BY defDims.id ASC %s"; // Limit goes here.
private static final String
FIND_METRIC_NAMES_SQL =
"SELECT distinct def.id, def.name "
+ "FROM MonMetrics.Definitions def "
+ "WHERE def.id IN (%s) "
+ "WHERE def.id IN (%s) " // Subselect goes here
+ "ORDER BY def.id ASC ";
private static final String
METRIC_NAMES_SUB_SELECT =
"SELECT defSub.id "
+ "FROM MonMetrics.Definitions defSub, MonMetrics.DefinitionDimensions defDimsSub"
+ "%s " // Dimensions inner join goes here if dimensions specified.
+ "FROM MonMetrics.Definitions defSub, MonMetrics.DefinitionDimensions defDimsSub "
+ "WHERE defDimsSub.definition_id = defSub.id "
+ "AND defSub.tenant_id = :tenantId "
+ "%s " // Offset goes here.
+ "%s " // Dimensions and clause goes here
+ "ORDER BY defSub.id ASC %s"; // Limit goes here.
private static final String TABLE_TO_JOIN_DIMENSIONS_ON = "defDimsSub";
@ -136,11 +127,11 @@ public class MetricDefinitionVerticaRepoImpl implements MetricDefinitionRepo {
// Can't bind limit in a nested sub query. So, just tack on as String.
String limitPart = " limit " + Integer.toString(limit + 1);
String
defSubSelect =
String defSubSelect =
String.format(METRIC_NAMES_SUB_SELECT,
MetricQueries.buildJoinClauseFor(dimensions, TABLE_TO_JOIN_DIMENSIONS_ON),
offsetPart, limitPart);
offsetPart,
MetricQueries.buildDimensionAndClause(dimensions, TABLE_TO_JOIN_DIMENSIONS_ON),
limitPart);
String sql = String.format(FIND_METRIC_NAMES_SQL, defSubSelect);
@ -235,7 +226,7 @@ public class MetricDefinitionVerticaRepoImpl implements MetricDefinitionRepo {
if (name != null && !name.isEmpty()) {
namePart = " and defSub.name = :name ";
namePart = " and def.name = :name ";
}
@ -243,20 +234,18 @@ public class MetricDefinitionVerticaRepoImpl implements MetricDefinitionRepo {
if (offset != null && !offset.isEmpty()) {
offsetPart = " and defdimsSub.id > :offset ";
offsetPart = " and defDims.id > :offset ";
}
// Can't bind limit in a nested sub query. So, just tack on as String.
String limitPart = " limit " + Integer.toString(limit + 1);
String
defSubSelect =
String.format(METRIC_DEFINITIONS_SUB_SELECT,
MetricQueries.buildJoinClauseFor(dimensions, TABLE_TO_JOIN_DIMENSIONS_ON),
namePart, offsetPart, limitPart);
String sql = String.format(FIND_METRIC_DEFS_SQL, defSubSelect);
String sql =
String.format(FIND_METRIC_DEFS_SQL,
namePart, offsetPart,
MetricQueries.buildDimensionAndClause(dimensions, "defDims"),
limitPart);
try (Handle h = db.open()) {

View File

@ -26,38 +26,33 @@ import monasca.common.persistence.SqlQueries;
final class MetricQueries {
private MetricQueries() {}
static String buildJoinClauseFor(Map<String, String> dimensions, String tableToJoinName) {
static String buildDimensionAndClause(Map<String, String> dimensions, String tableToJoinName) {
StringBuilder sb = null;
if (dimensions != null) {
if (dimensions != null && dimensions.size() > 0) {
int numDims = dimensions.size();
sb = new StringBuilder();
sb.append(" and " + tableToJoinName + ".dimension_set_id in ")
.append("(select dimension_set_id from MonMetrics.Dimensions where ");
for (int i = 0; i < dimensions.size(); i++) {
sb
.append(" inner join MonMetrics.Dimensions dim")
.append(i)
.append(" on dim")
.append(i)
.append(".name = :dname")
.append(i)
.append(" and dim")
.append(i)
.append(".value = " + ":dvalue")
.append(i)
.append(" and " + tableToJoinName + ".dimension_set_id = dim")
.append(i)
.append(".dimension_set_id");
for (int i = 0; i < numDims; i++) {
sb.append("name = :dname")
.append(i)
.append(" and value = :dvalue")
.append(i);
if (i != (numDims - 1)) {
sb.append(" or ");
}
}
sb.append(" group by dimension_set_id ")
.append(" having count(*) = " + numDims +") ");
}
return sb == null ? "" : sb.toString();
}
static Map<String, String> dimensionsFor(Handle handle, byte[] dimensionSetId) {
return SqlQueries.keyValuesFor(handle, "select name, value from MonMetrics.Dimensions "

View File

@ -52,9 +52,9 @@ public class StatisticVerticaRepoImpl implements StatisticRepo {
"select defdims.id, def.name, d.name as dname, d.value as dvalue "
+ "from MonMetrics.Definitions def, MonMetrics.DefinitionDimensions defdims "
+ "left outer join MonMetrics.Dimensions d on d.dimension_set_id = defdims.dimension_set_id "
+ "%s "
+ "where def.id = defdims.definition_id and def.tenant_id = :tenantId "
+ "%s "
+ "%s " // metric name here
+ "%s " // dimension and clause here
+ "order by defdims.id ASC";
private static final String TABLE_TO_JOIN_DIMENSIONS_ON = "defdims";
@ -208,8 +208,8 @@ public class StatisticVerticaRepoImpl implements StatisticRepo {
String sql =
String
.format(FIND_BY_METRIC_DEF_SQL,
MetricQueries.buildJoinClauseFor(dimensions, TABLE_TO_JOIN_DIMENSIONS_ON),
sb);
sb,
MetricQueries.buildDimensionAndClause(dimensions, TABLE_TO_JOIN_DIMENSIONS_ON));
Query<Map<String, Object>> query =
h.createQuery(sql)

View File

@ -26,30 +26,29 @@ public class MetricQueriesTest {
private final static String TABLE_TO_JOIN_DIMENSIONS_ON = "defdims";
public void metricQueriesBuildJoinClauseForTest1() {
public void metricQueriesBuildDimensionAndClauseTest1() {
String expectedResult =
" inner join MonMetrics.Dimensions dim0 on dim0.name = :dname0 and dim0" + ".value "
+ "= :dvalue0 and defdims.dimension_set_id = dim0.dimension_set_id inner join "
+ "MonMetrics.Dimensions dim1 on dim1.name = :dname1 and dim1.value = :dvalue1 and defdims"
+ ".dimension_set_id = dim1.dimension_set_id";
" and defdims.dimension_set_id in (select dimension_set_id from MonMetrics.Dimensions "
+ "where name = :dname0 and value = :dvalue0 or name = :dname1 and value = :dvalue1 "
+ "group by dimension_set_id having count(*) = 2) ";
Map<String, String> dimsMap = new HashMap<>();
dimsMap.put("foo", "bar");
dimsMap.put("biz", "baz");
String s = MetricQueries.buildJoinClauseFor(dimsMap, TABLE_TO_JOIN_DIMENSIONS_ON);
String s = MetricQueries.buildDimensionAndClause(dimsMap, TABLE_TO_JOIN_DIMENSIONS_ON);
assertEquals(expectedResult, s);
}
public void metricQueriesBuildJoinClauseForTest2() {
public void metricQueriesBuildDimensionAndClauseTest2() {
String expectedResult = "";
Map<String, String> dimsMap = new HashMap<>();
assertEquals(expectedResult, MetricQueries.buildJoinClauseFor(dimsMap,TABLE_TO_JOIN_DIMENSIONS_ON));
assertEquals(expectedResult, MetricQueries.buildDimensionAndClause(dimsMap,TABLE_TO_JOIN_DIMENSIONS_ON));
}
public void metricQueriesBuildJoinClauseForTest3() {
public void metricQueriesBuildDimensionAndClauseForTest3() {
String expectedResult = "";
Map<String, String> dimsMap = null;
assertEquals(expectedResult, MetricQueries.buildJoinClauseFor(dimsMap, TABLE_TO_JOIN_DIMENSIONS_ON));
assertEquals(expectedResult, MetricQueries.buildDimensionAndClause(dimsMap, TABLE_TO_JOIN_DIMENSIONS_ON));
}
}