Merge "Optimize queries for open/merged changes by project + branch"

This commit is contained in:
Shawn Pearce
2012-04-02 12:00:36 -07:00
committed by gerrit code review
6 changed files with 165 additions and 1 deletions

View File

@@ -101,6 +101,16 @@ public interface ChangeAccess extends Access<Change, Change.Id> {
ResultSet<Change> allClosedNext(char status, String sortKey, int limit) ResultSet<Change> allClosedNext(char status, String sortKey, int limit)
throws OrmException; throws OrmException;
@Query("WHERE open = false AND status = ? AND dest = ? AND sortKey > ?"
+ " ORDER BY sortKey LIMIT ?")
ResultSet<Change> byBranchClosedPrev(char status, Branch.NameKey p,
String sortKey, int limit) throws OrmException;
@Query("WHERE open = false AND status = ? AND dest = ? AND sortKey < ?"
+ " ORDER BY sortKey DESC LIMIT ?")
ResultSet<Change> byBranchClosedNext(char status, Branch.NameKey p,
String sortKey, int limit) throws OrmException;
@Query @Query
ResultSet<Change> all() throws OrmException; ResultSet<Change> all() throws OrmException;
} }

View File

@@ -109,6 +109,10 @@ ON changes (dest_project_name);
CREATE INDEX changes_allClosed CREATE INDEX changes_allClosed
ON changes (open, status, sort_key); ON changes (open, status, sort_key);
-- covers: byBranchClosedPrev, byBranchClosedNext
CREATE INDEX changes_byBranchClosed
ON changes (status, dest_project_name, dest_branch_name, sort_key);
CREATE INDEX changes_key CREATE INDEX changes_key
ON changes (change_key); ON changes (change_key);

View File

@@ -187,6 +187,11 @@ WHERE open = 'N';
CREATE INDEX changes_byProject CREATE INDEX changes_byProject
ON changes (dest_project_name); ON changes (dest_project_name);
-- covers: byBranchClosedPrev, byBranchClosedNext
CREATE INDEX changes_byBranchClosed
ON changes (status, dest_project_name, dest_branch_name, sort_key)
WHERE open = 'N';
CREATE INDEX changes_key CREATE INDEX changes_key
ON changes (change_key); ON changes (change_key);

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.query.change; package com.google.gerrit.server.query.change;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ChangeAccess; import com.google.gerrit.reviewdb.server.ChangeAccess;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -118,6 +119,102 @@ public class ChangeQueryRewriter extends QueryRewriter<ChangeData> {
return a.getValue().compareTo(b.getValue()) >= 0 ? a : b; return a.getValue().compareTo(b.getValue()) >= 0 ? a : b;
} }
@Rewrite("status:open P=(project:*) B=(branch:*) S=(sortkey_after:*) L=(limit:*)")
public Predicate<ChangeData> r05_byBranchOpenPrev(
@Named("P") final ProjectPredicate p,
@Named("B") final BranchPredicate b,
@Named("S") final SortKeyPredicate.After s,
@Named("L") final IntPredicate<ChangeData> l) {
return new PaginatedSource(500, s.getValue(), l.intValue()) {
@Override
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
throws OrmException {
return a.byBranchOpenAll(new Branch.NameKey(p.getValueKey(), b
.getValue()));
}
@Override
public boolean match(ChangeData cd) throws OrmException {
return cd.change(dbProvider).getStatus().isOpen() //
&& p.match(cd) //
&& b.match(cd) //
&& s.match(cd);
}
};
}
@Rewrite("status:open P=(project:*) B=(branch:*) S=(sortkey_before:*) L=(limit:*)")
public Predicate<ChangeData> r05_byBranchOpenNext(
@Named("P") final ProjectPredicate p,
@Named("B") final BranchPredicate b,
@Named("S") final SortKeyPredicate.Before s,
@Named("L") final IntPredicate<ChangeData> l) {
return new PaginatedSource(500, s.getValue(), l.intValue()) {
@Override
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
throws OrmException {
return a.byBranchOpenAll(new Branch.NameKey(p.getValueKey(), b
.getValue()));
}
@Override
public boolean match(ChangeData cd) throws OrmException {
return cd.change(dbProvider).getStatus().isOpen() //
&& p.match(cd) //
&& b.match(cd) //
&& s.match(cd);
}
};
}
@Rewrite("status:merged P=(project:*) B=(branch:*) S=(sortkey_after:*) L=(limit:*)")
public Predicate<ChangeData> r05_byBranchMergedPrev(
@Named("P") final ProjectPredicate p,
@Named("B") final BranchPredicate b,
@Named("S") final SortKeyPredicate.After s,
@Named("L") final IntPredicate<ChangeData> l) {
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
@Override
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
throws OrmException {
return a.byBranchClosedPrev(Change.Status.MERGED.getCode(), //
new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
}
@Override
public boolean match(ChangeData cd) throws OrmException {
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
&& p.match(cd) //
&& b.match(cd) //
&& s.match(cd);
}
};
}
@Rewrite("status:merged P=(project:*) B=(branch:*) S=(sortkey_before:*) L=(limit:*)")
public Predicate<ChangeData> r05_byBranchMergedNext(
@Named("P") final ProjectPredicate p,
@Named("B") final BranchPredicate b,
@Named("S") final SortKeyPredicate.Before s,
@Named("L") final IntPredicate<ChangeData> l) {
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
@Override
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
throws OrmException {
return a.byBranchClosedNext(Change.Status.MERGED.getCode(), //
new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
}
@Override
public boolean match(ChangeData cd) throws OrmException {
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
&& p.match(cd) //
&& b.match(cd) //
&& s.match(cd);
}
};
}
@Rewrite("status:open P=(project:*) S=(sortkey_after:*) L=(limit:*)") @Rewrite("status:open P=(project:*) S=(sortkey_after:*) L=(limit:*)")
public Predicate<ChangeData> r10_byProjectOpenPrev( public Predicate<ChangeData> r10_byProjectOpenPrev(
@Named("P") final ProjectPredicate p, @Named("P") final ProjectPredicate p,

View File

@@ -32,7 +32,7 @@ import java.util.List;
/** A version of the database schema. */ /** A version of the database schema. */
public abstract class SchemaVersion { public abstract class SchemaVersion {
/** The current schema version. */ /** The current schema version. */
public static final Class<Schema_62> C = Schema_62.class; public static final Class<Schema_63> C = Schema_63.class;
public static class Module extends AbstractModule { public static class Module extends AbstractModule {
@Override @Override

View File

@@ -0,0 +1,48 @@
// Copyright (C) 2012 The Android Open Source Project
//
// 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 the License.
package com.google.gerrit.server.schema;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.schema.sql.DialectPostgreSQL;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.SQLException;
import java.sql.Statement;
public class Schema_63 extends SchemaVersion {
@Inject
Schema_63(Provider<Schema_62> prior) {
super(prior);
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException {
Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
try {
if (((JdbcSchema) db).getDialect() instanceof DialectPostgreSQL) {
stmt.execute("CREATE INDEX changes_byBranchClosed"
+ " ON changes (status, dest_project_name, dest_branch_name, sort_key)"
+ " WHERE open = 'N'");
} else {
stmt.execute("CREATE INDEX changes_byBranchClosed"
+ " ON changes (status, dest_project_name, dest_branch_name, sort_key)");
}
} finally {
stmt.close();
}
}
}