[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] [metrics-web/master] Improve relay search performance for very broad searches.
Author: Karsten Loesing <karsten.loesing@xxxxxxx>
Date: Mon, 20 Sep 2010 14:25:35 +0200
Subject: Improve relay search performance for very broad searches.
Commit: 2f0b785a5426fd31a2a5176b91f5e2e2876611ef
Searches with very broad search terms, like 1-character nicknames,
resulted in lots of possible matches of which we would only display the
last 30 anyway. These searches could take up to 1 minute or more. Improve
these searches by adding an index on validafter and asking for validafter
instead of DATE_TRUNC('month', validafter).
Also print out the query if it took longer than 10 seconds, so that people
can tell us which queries are slow.
---
.../torproject/ernie/web/RelaySearchServlet.java | 47 +++++++++++++++-----
1 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/src/org/torproject/ernie/web/RelaySearchServlet.java b/src/org/torproject/ernie/web/RelaySearchServlet.java
index 91e66a9..71a6780 100644
--- a/src/org/torproject/ernie/web/RelaySearchServlet.java
+++ b/src/org/torproject/ernie/web/RelaySearchServlet.java
@@ -51,9 +51,13 @@ public class RelaySearchServlet extends HttpServlet {
private static SimpleDateFormat monthFormat =
new SimpleDateFormat("yyyy-MM");
+ private static SimpleDateFormat dateTimeFormat =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
static {
dayFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
monthFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private Connection conn = null;
@@ -242,6 +246,8 @@ public class RelaySearchServlet extends HttpServlet {
SortedSet<String> searchFingerprintOrNickname = new TreeSet<String>();
SortedSet<String> searchDays = new TreeSet<String>();
SortedSet<String> searchMonths = new TreeSet<String>();
+ SortedSet<Long> searchDayTimestamps = new TreeSet<Long>();
+ SortedSet<Long> searchMonthTimestamps = new TreeSet<Long>();
boolean validQuery = false;
/* Only parse search parameter if it contains nothing else than
@@ -299,10 +305,12 @@ public class RelaySearchServlet extends HttpServlet {
searchTerm.startsWith("20")) {
try {
if (searchTerm.length() == 10) {
- dayFormat.parse(searchTerm);
+ searchDayTimestamps.add(dayFormat.parse(searchTerm).
+ getTime());
searchDays.add(searchTerm);
} else if (searchTerm.length() == 7) {
- monthFormat.parse(searchTerm);
+ searchMonthTimestamps.add(monthFormat.parse(searchTerm).
+ getTime());
searchMonths.add(searchTerm);
} else {
validQuery = false;
@@ -454,24 +462,32 @@ public class RelaySearchServlet extends HttpServlet {
StringBuilder query = new StringBuilder("SELECT validafter, "
+ "rawdesc FROM statusentry WHERE ");
boolean addAnd = false;
- if (searchDays.size() > 0 || searchMonths.size() > 0) {
+ if (searchDayTimestamps.size() > 0 ||
+ searchMonthTimestamps.size() > 0) {
boolean addOr = false;
query.append("(");
- for (String search : searchDays) {
- query.append((addOr ? "OR " : "") + "DATE_TRUNC('day', "
- + "validafter) = '" + search + " 00:00:00' ");
+ for (long searchTimestamp : searchDayTimestamps) {
+ query.append((addOr ? "OR " : "") + "(validafter >= '"
+ + dateTimeFormat.format(searchTimestamp) + "' AND "
+ + "validafter < '" + dateTimeFormat.format(searchTimestamp
+ + 24L * 60L * 60L * 1000L) + "') ");
addOr = true;
}
- for (String search : searchMonths) {
- query.append((addOr ? "OR " : "") + "DATE_TRUNC('month', "
- + "validafter) = '" + search + "-01 00:00:00' ");
+ for (long searchTimestamp : searchMonthTimestamps) {
+ Calendar firstOfNextMonth = Calendar.getInstance(
+ TimeZone.getTimeZone("UTC"));
+ firstOfNextMonth.setTimeInMillis(searchTimestamp);
+ firstOfNextMonth.add(Calendar.MONTH, 1);
+ query.append((addOr ? "OR " : "") + "(validafter >= '"
+ + dateTimeFormat.format(searchTimestamp) + "' AND "
+ + "validafter < '" + dateTimeFormat.format(
+ firstOfNextMonth.getTimeInMillis()) + "') ");
addOr = true;
}
query.append(") ");
} else {
- query.append("DATE_TRUNC('day', validafter) >= '"
- + dayFormat.format(started - 30L * 24L * 60L * 60L * 1000L)
- + " 00:00:00' ");
+ query.append("validafter >= '" + dateTimeFormat.format(
+ started - 30L * 24L * 60L * 60L * 1000L) + "' ");
}
if (searchNickname.length() > 0) {
query.append("AND LOWER(nickname) LIKE '"
@@ -557,6 +573,13 @@ public class RelaySearchServlet extends HttpServlet {
"(displaying only the first 30 hits) " : "") + "in "
+ String.format("%d.%03d", searchTime / 1000, searchTime % 1000)
+ " seconds.</p>\n");
+ if (searchTime > 10L * 1000L) {
+ out.write(" <p>In theory, search time should not exceed "
+ + "10 seconds. The query was '" + query + "'. If this or "
+ + "similar searches remain slow, please "
+ + "<a href=\"mailto:tor-assistants@xxxxxxxxxxxxx\">let us "
+ + "know</a>!</p>\n");
+ }
/* Finish writing response. */
writeFooter(out);
--
1.7.1