mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-10065: Optimize SQL queries in listTemplate API to improve performance (#2260)
The db queries in listTemplateAPI could be optimized to get unique results from the database which could help in reducing the listTemplate API response time.
This commit is contained in:
parent
ebb7a5279d
commit
7253969088
@ -276,4 +276,6 @@ public interface GenericDao<T, ID extends Serializable> {
|
||||
Pair<List<T>, Integer> searchAndDistinctCount(final SearchCriteria<T> sc, final Filter filter);
|
||||
|
||||
Map<String, Attribute> getAllAttributes();
|
||||
|
||||
Pair<List<T>, Integer> searchAndDistinctCount(final SearchCriteria<T> sc, final Filter filter, final String[] distinctColumns);
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import javax.naming.ConfigurationException;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.Column;
|
||||
@ -1326,6 +1326,14 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
|
||||
return new Pair<List<T>, Integer>(objects, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB()
|
||||
public Pair<List<T>, Integer> searchAndDistinctCount(final SearchCriteria<T> sc, final Filter filter, final String[] distinctColumns) {
|
||||
List<T> objects = search(sc, filter, null, false);
|
||||
Integer count = getDistinctCount(sc, distinctColumns);
|
||||
return new Pair<List<T>, Integer>(objects, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB()
|
||||
public List<T> search(final SearchCriteria<T> sc, final Filter filter, final boolean enableQueryCache) {
|
||||
@ -1927,6 +1935,52 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getDistinctCount(SearchCriteria<T> sc, String[] distinctColumns) {
|
||||
String clause = sc != null ? sc.getWhereClause() : null;
|
||||
if (Strings.isNullOrEmpty(clause)) {
|
||||
clause = null;
|
||||
}
|
||||
|
||||
final StringBuilder str = createDistinctSelect(sc, clause != null, distinctColumns);
|
||||
if (clause != null) {
|
||||
str.append(clause);
|
||||
}
|
||||
|
||||
Collection<JoinBuilder<SearchCriteria<?>>> joins = null;
|
||||
if (sc != null) {
|
||||
joins = sc.getJoins();
|
||||
if (joins != null) {
|
||||
addJoins(str, joins);
|
||||
}
|
||||
}
|
||||
|
||||
final TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||
final String sql = "SELECT COUNT(*) FROM (" + str.toString() + ") AS tmp";
|
||||
|
||||
try (PreparedStatement pstmt = txn.prepareAutoCloseStatement(sql)) {
|
||||
int i = 1;
|
||||
if (clause != null) {
|
||||
for (final Pair<Attribute, Object> value : sc.getValues()) {
|
||||
prepareAttribute(i++, pstmt, value.first(), value.second());
|
||||
}
|
||||
}
|
||||
|
||||
if (joins != null) {
|
||||
i = addJoinAttributes(i, pstmt, joins);
|
||||
}
|
||||
|
||||
final ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
return rs.getInt(1);
|
||||
}
|
||||
return 0;
|
||||
} catch (final SQLException e) {
|
||||
throw new CloudRuntimeException("DB Exception in executing: " + sql, e);
|
||||
} catch (final Throwable e) {
|
||||
throw new CloudRuntimeException("Caught exception in : " + sql, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getCount(SearchCriteria<T> sc) {
|
||||
String clause = sc != null ? sc.getWhereClause() : null;
|
||||
if (clause != null && clause.length() == 0) {
|
||||
@ -2013,4 +2067,18 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
|
||||
Integer count = getCount(sc);
|
||||
return new Pair<List<T>, Integer>(objects, count);
|
||||
}
|
||||
|
||||
@DB()
|
||||
protected StringBuilder createDistinctSelect(SearchCriteria<?> sc, final boolean whereClause, String[] distinctColumns) {
|
||||
final SqlGenerator generator = new SqlGenerator(_entityBeanType);
|
||||
String distinctSql = generator.buildDistinctSql(distinctColumns);
|
||||
|
||||
StringBuilder sql = new StringBuilder(distinctSql);
|
||||
|
||||
if (!whereClause) {
|
||||
sql.delete(sql.length() - (_discriminatorClause == null ? 6 : 4), sql.length());
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
|
||||
@ -680,4 +680,20 @@ public class SqlGenerator {
|
||||
|
||||
return sql.append("SELECT DISTINCT id FROM ").append(buildTableReferences()).append(" WHERE ").append(buildDiscriminatorClause().first()).toString();
|
||||
}
|
||||
|
||||
public String buildDistinctSql(String[] distinctColumnNames) {
|
||||
StringBuilder sbColumn = new StringBuilder();
|
||||
|
||||
if (distinctColumnNames != null && distinctColumnNames.length > 0) {
|
||||
for (String columnName : distinctColumnNames) {
|
||||
sbColumn.append(columnName).append(", ");
|
||||
}
|
||||
sbColumn.delete(sbColumn.length() - 2, sbColumn.length());
|
||||
} else {
|
||||
sbColumn.append("*");
|
||||
}
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
return sql.append("SELECT DISTINCT " + sbColumn.toString() + " FROM ").append(buildTableReferences()).append(" WHERE ").append(buildDiscriminatorClause().first()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3383,7 +3383,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter);
|
||||
} else {
|
||||
sc.addAnd("templateState", SearchCriteria.Op.IN, new State[]{State.Active, State.UploadAbandoned, State.UploadError, State.NotUploaded, State.UploadInProgress});
|
||||
uniqueTmplPair = _templateJoinDao.searchAndCount(sc, searchFilter);
|
||||
final String[] distinctColumns = {"temp_zone_pair"};
|
||||
uniqueTmplPair = _templateJoinDao.searchAndDistinctCount(sc, searchFilter, distinctColumns);
|
||||
}
|
||||
|
||||
Integer count = uniqueTmplPair.second();
|
||||
|
||||
@ -278,6 +278,11 @@ public class MockUsageEventDao implements UsageEventDao{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<UsageEventVO>, Integer> searchAndDistinctCount(SearchCriteria<UsageEventVO> sc, Filter filter, String[] distinctColumns) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UsageEventVO> listLatestEvents(Date endDate) {
|
||||
return null;
|
||||
@ -303,5 +308,4 @@ public class MockUsageEventDao implements UsageEventDao{
|
||||
public void saveDetails(long eventId, Map<String, String> details) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user