From 53adc8e7ec963416a188dc98b2bbf9a41676f91c Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Thu, 13 Dec 2018 18:40:13 +0200 Subject: [PATCH] Sessions table structure optimization - Replaced user_id with uuid - Replaced server_id with server_uuid --- .../system/database/databases/sql/SQLDB.java | 3 +- .../patches/SessionsOptimizationPatch.java | 82 ++++++++++++++++ .../sql/patches/WorldsServerIDPatch.java | 6 +- .../databases/sql/tables/SessionsTable.java | 97 ++++++++++--------- 4 files changed, 136 insertions(+), 52 deletions(-) create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionsOptimizationPatch.java diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java index 666cca03b..9b546cee2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java @@ -202,8 +202,9 @@ public abstract class SQLDB extends Database { new NicknameLastSeenPatch(this), new VersionTableRemovalPatch(this), new DiskUsagePatch(this), + new WorldsOptimizationPatch(this), new WorldTimesOptimizationPatch(this), - new WorldsOptimizationPatch(this) + new SessionsOptimizationPatch(this) }; try { diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionsOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionsOptimizationPatch.java new file mode 100644 index 000000000..a04c542ed --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionsOptimizationPatch.java @@ -0,0 +1,82 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.system.database.databases.sql.patches; + +import com.djrapitops.plan.api.exceptions.database.DBOpException; +import com.djrapitops.plan.system.database.databases.sql.SQLDB; +import com.djrapitops.plan.system.database.databases.sql.tables.SessionsTable; +import com.djrapitops.plan.system.database.databases.sql.tables.SessionsTable.Col; + +public class SessionsOptimizationPatch extends Patch { + + private String tempTableName; + private String tableName; + + public SessionsOptimizationPatch(SQLDB db) { + super(db); + tableName = SessionsTable.TABLE_NAME; + tempTableName = "temp_sessions"; + } + + @Override + public boolean hasBeenApplied() { + return hasColumn(tableName, Col.UUID.get()) + && hasColumn(tableName, Col.SERVER_UUID.get()) + && !hasColumn(tableName, "user_id") + && !hasColumn(tableName, "server_id") + && !hasTable(tempTableName); // If this table exists the patch has failed to finish. + } + + @Override + public void apply() { + try { + tempOldTable(); + db.getSessionsTable().createTable(); + + db.execute("INSERT INTO " + tableName + " (" + + Col.UUID + ", " + + Col.SERVER_UUID + ", " + + Col.ID + ", " + + Col.SESSION_START + ", " + + Col.SESSION_END + ", " + + Col.MOB_KILLS + ", " + + Col.DEATHS + ", " + + Col.AFK_TIME + + ") SELECT " + + "(SELECT plan_users.uuid FROM plan_users WHERE plan_users.id = " + tempTableName + ".user_id LIMIT 1), " + + "(SELECT plan_servers.uuid FROM plan_servers WHERE plan_servers.id = " + tempTableName + ".server_id LIMIT 1), " + + Col.ID + ", " + + Col.SESSION_START + ", " + + Col.SESSION_END + ", " + + Col.MOB_KILLS + ", " + + Col.DEATHS + ", " + + Col.AFK_TIME + + " FROM " + tempTableName + ); + + dropTable(tempTableName); + } catch (Exception e) { + throw new DBOpException(SessionsOptimizationPatch.class.getSimpleName() + " failed.", e); + } + } + + private void tempOldTable() { + if (!hasTable(tempTableName)) { + renameTable(tableName, tempTableName); + } + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/WorldsServerIDPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/WorldsServerIDPatch.java index 18273fc71..de5ea70c9 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/WorldsServerIDPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/WorldsServerIDPatch.java @@ -89,19 +89,17 @@ public class WorldsServerIDPatch extends Patch { WorldTimesTable worldTimesTable = db.getWorldTimesTable(); SessionsTable sessionsTable = db.getSessionsTable(); - String statementSelectServerID = db.getServerTable().statementSelectServerID; - String worldIDColumn = worldTimesTable + "." + WorldTimesTable.Col.WORLD_ID; String worldSessionIDColumn = worldTimesTable + "." + WorldTimesTable.Col.SESSION_ID; String sessionIDColumn = sessionsTable + "." + SessionsTable.Col.ID; - String sessionServerIDColumn = sessionsTable + "." + SessionsTable.Col.SERVER_ID; + String sessionServerUUIDColumn = sessionsTable + "." + SessionsTable.Col.SERVER_UUID; String sql = "SELECT DISTINCT " + WorldTable.Col.NAME + " FROM " + WorldTable.TABLE_NAME + " INNER JOIN " + worldTimesTable + " on " + worldIDColumn + "=" + WorldTable.TABLE_NAME + "." + WorldTable.Col.ID + " INNER JOIN " + sessionsTable + " on " + worldSessionIDColumn + "=" + sessionIDColumn + - " WHERE " + statementSelectServerID + "=" + sessionServerIDColumn; + " WHERE " + sessionServerUUIDColumn + "=?"; return query(new QueryStatement>(sql, 1000) { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java index 9c0c4676b..a4512c78b 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java @@ -37,45 +37,45 @@ import java.util.function.Function; import java.util.stream.Collectors; /** + * Table that represents plan_sessions. + * + * Patches related to this table: + * {@link com.djrapitops.plan.system.database.databases.sql.patches.Version10Patch} + * {@link com.djrapitops.plan.system.database.databases.sql.patches.SessionAFKTimePatch} + * {@link com.djrapitops.plan.system.database.databases.sql.patches.SessionsOptimizationPatch} + * * @author Rsl1122 */ public class SessionsTable extends UserIDTable { public static final String TABLE_NAME = "plan_sessions"; - private final ServerTable serverTable; private String insertStatement; public SessionsTable(SQLDB db) { super(TABLE_NAME, db); - serverTable = db.getServerTable(); insertStatement = "INSERT INTO " + tableName + " (" - + Col.USER_ID + ", " + + Col.UUID + ", " + Col.SESSION_START + ", " + Col.SESSION_END + ", " + Col.DEATHS + ", " + Col.MOB_KILLS + ", " + Col.AFK_TIME + ", " - + Col.SERVER_ID - + ") VALUES (" - + usersTable.statementSelectID + ", " - + "?, ?, ?, ?, ?, " - + serverTable.statementSelectServerID + ")"; + + Col.SERVER_UUID + + ") VALUES (?, ?, ?, ?, ?, ?, ?)"; } @Override public void createTable() throws DBInitException { createTable(TableSqlParser.createTable(this.tableName) .primaryKeyIDColumn(supportsMySQLQueries, Col.ID) - .column(Col.USER_ID, Sql.INT).notNull() - .column(Col.SERVER_ID, Sql.INT).notNull() + .column(Col.UUID, Sql.varchar(36)).notNull() + .column(Col.SERVER_UUID, Sql.varchar(36)).notNull() .column(Col.SESSION_START, Sql.LONG).notNull() .column(Col.SESSION_END, Sql.LONG).notNull() .column(Col.MOB_KILLS, Sql.INT).notNull() .column(Col.DEATHS, Sql.INT).notNull() .column(Col.AFK_TIME, Sql.LONG).notNull() - .foreignKey(Col.USER_ID, usersTable.getTableName(), UsersTable.Col.ID) - .foreignKey(Col.SERVER_ID, serverTable.getTableName(), ServerTable.Col.SERVER_ID) .primaryKey(supportsMySQLQueries, Col.ID) .toString() ); @@ -90,7 +90,7 @@ public class SessionsTable extends UserIDTable { */ private int getSessionID(UUID uuid, Session session) { String sql = "SELECT " + Col.ID + " FROM " + tableName + - " WHERE " + Col.USER_ID + "=" + usersTable.statementSelectID + + " WHERE " + Col.UUID + "=?" + " AND " + Col.SESSION_START + "=?" + " AND " + Col.SESSION_END + "=?"; @@ -164,9 +164,8 @@ public class SessionsTable extends UserIDTable { * @return Map with Sessions that don't contain Kills or WorldTimes. */ private Map> getSessionInformation(UUID uuid) { - Map serverUUIDs = serverTable.getServerUUIDsByID(); String sql = Select.from(tableName, "*") - .where(Col.USER_ID + "=" + usersTable.statementSelectID) + .where(Col.UUID + "=?") .toString(); return query(new QueryStatement>>(sql, 10000) { @@ -182,11 +181,7 @@ public class SessionsTable extends UserIDTable { int id = set.getInt(Col.ID.get()); long start = set.getLong(Col.SESSION_START.get()); long end = set.getLong(Col.SESSION_END.get()); - UUID serverUUID = serverUUIDs.get(set.getInt(Col.SERVER_ID.get())); - - if (serverUUID == null) { - throw new IllegalStateException("Server not present"); - } + UUID serverUUID = UUID.fromString(set.getString(Col.SERVER_UUID.get())); long timeAFK = set.getLong(Col.AFK_TIME.get()); @@ -214,8 +209,8 @@ public class SessionsTable extends UserIDTable { " (SUM(" + Col.SESSION_END + ") - SUM(" + Col.SESSION_START + ")) as playtime" + " FROM " + tableName + " WHERE " + Col.SESSION_START + ">?" + - " AND " + Col.USER_ID + "=" + usersTable.statementSelectID + - " AND " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID; + " AND " + Col.UUID + "=?" + + " AND " + Col.SERVER_UUID + "=?"; return query(new QueryStatement(sql) { @Override @@ -291,7 +286,7 @@ public class SessionsTable extends UserIDTable { " (SUM(" + Col.SESSION_END + ") - SUM(" + Col.SESSION_START + ")) as playtime" + " FROM " + tableName + " WHERE " + Col.SESSION_START + ">?" + - " AND " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID; + " AND " + Col.SERVER_UUID + "=?"; return query(new QueryStatement(sql) { @Override @@ -333,8 +328,8 @@ public class SessionsTable extends UserIDTable { " COUNT(*) as logintimes" + " FROM " + tableName + " WHERE (" + Col.SESSION_START + " >= ?)" + - " AND " + Col.USER_ID + "=" + usersTable.statementSelectID + - " AND " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID; + " AND " + Col.UUID + "=?" + + " AND " + Col.SERVER_UUID + "=?"; return query(new QueryStatement(sql) { @Override @@ -376,19 +371,16 @@ public class SessionsTable extends UserIDTable { } public Map> getSessionInfoOfServer(UUID serverUUID) { - String usersIDColumn = usersTable + "." + UsersTable.Col.ID; - String usersUUIDColumn = usersTable + "." + UsersTable.Col.UUID + " as uuid"; String sql = "SELECT " + tableName + "." + Col.ID + ", " + + Col.UUID + ", " + Col.SESSION_START + ", " + Col.SESSION_END + ", " + Col.DEATHS + ", " + Col.MOB_KILLS + ", " + - Col.AFK_TIME + ", " + - usersUUIDColumn + + Col.AFK_TIME + " FROM " + tableName + - " INNER JOIN " + usersTable + " on " + usersIDColumn + "=" + Col.USER_ID + - " WHERE " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID; + " WHERE " + Col.SERVER_UUID + "=?"; return query(new QueryStatement>>(sql, 5000) { @Override @@ -400,7 +392,8 @@ public class SessionsTable extends UserIDTable { public Map> processResults(ResultSet set) throws SQLException { Map> sessionsByUser = new HashMap<>(); while (set.next()) { - UUID uuid = UUID.fromString(set.getString("uuid")); + int id = set.getInt(Col.ID.get()); + UUID uuid = UUID.fromString(set.getString(Col.UUID.get())); long start = set.getLong(Col.SESSION_START.get()); long end = set.getLong(Col.SESSION_END.get()); @@ -410,7 +403,7 @@ public class SessionsTable extends UserIDTable { long timeAFK = set.getLong(Col.AFK_TIME.get()); List sessions = sessionsByUser.getOrDefault(uuid, new ArrayList<>()); - sessions.add(new Session(set.getInt(Col.ID.get()), uuid, serverUUID, start, end, mobKills, deaths, timeAFK)); + sessions.add(new Session(id, uuid, serverUUID, start, end, mobKills, deaths, timeAFK)); sessionsByUser.put(uuid, sessions); } return sessionsByUser; @@ -423,14 +416,11 @@ public class SessionsTable extends UserIDTable { } public Map getLastSeenForAllPlayers() { - String usersIDColumn = usersTable + "." + UsersTable.Col.ID; - String usersUUIDColumn = usersTable + "." + UsersTable.Col.UUID + " as uuid"; String sql = "SELECT" + " MAX(" + Col.SESSION_END + ") as last_seen, " + - usersUUIDColumn + + Col.UUID + " FROM " + tableName + - " INNER JOIN " + usersTable + " on " + usersIDColumn + "=" + Col.USER_ID + - " GROUP BY uuid"; + " GROUP BY " + Col.UUID; return query(new QueryAllStatement>(sql, 20000) { @Override @@ -447,13 +437,10 @@ public class SessionsTable extends UserIDTable { } public Map>> getAllSessions(boolean getKillsAndWorldTimes) { - Map uuidsByID = usersTable.getUUIDsByID(); - Map serverUUIDsByID = serverTable.getServerUUIDsByID(); - String sql = "SELECT " + Col.ID + ", " + - Col.USER_ID + ", " + - Col.SERVER_ID + ", " + + Col.UUID + ", " + + Col.SERVER_UUID + ", " + Col.SESSION_START + ", " + Col.SESSION_END + ", " + Col.DEATHS + ", " + @@ -466,8 +453,8 @@ public class SessionsTable extends UserIDTable { public Map>> processResults(ResultSet set) throws SQLException { Map>> map = new HashMap<>(); while (set.next()) { - UUID serverUUID = serverUUIDsByID.get(set.getInt(Col.SERVER_ID.get())); - UUID uuid = uuidsByID.get(set.getInt(Col.USER_ID.get())); + UUID serverUUID = UUID.fromString(set.getString(Col.SERVER_UUID.get())); + UUID uuid = UUID.fromString(set.getString(Col.UUID.get())); Map> sessionsByUser = map.getOrDefault(serverUUID, new HashMap<>()); List sessions = sessionsByUser.getOrDefault(uuid, new ArrayList<>()); @@ -595,7 +582,7 @@ public class SessionsTable extends UserIDTable { public Map getIDServerIDRelation() { String sql = "SELECT " + Col.ID + ", " + - Col.SERVER_ID + + "(SELECT plan_servers.id FROM plan_servers WHERE plan_servers.uuid=" + Col.SERVER_UUID + ") as server_id" + " FROM " + tableName; return query(new QueryAllStatement>(sql, 10000) { @@ -603,17 +590,33 @@ public class SessionsTable extends UserIDTable { public Map processResults(ResultSet set) throws SQLException { Map idServerIdMap = new HashMap<>(); while (set.next()) { - idServerIdMap.put(set.getInt(Col.ID.get()), set.getInt(Col.SERVER_ID.get())); + idServerIdMap.put(set.getInt(Col.ID.get()), set.getInt("server_id")); } return idServerIdMap; } }); } + @Override + public void removeUser(UUID uuid) { + String sql = "DELETE FROM " + tableName + " WHERE (" + Col.UUID + "=?)"; + + execute(new ExecStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setString(1, uuid.toString()); + } + }); + } + public enum Col implements Column { + @Deprecated USER_ID(UserIDTable.Col.USER_ID.get()), + UUID("uuid"), ID("id"), + @Deprecated SERVER_ID("server_id"), + SERVER_UUID("server_uuid"), SESSION_START("session_start"), SESSION_END("session_end"), MOB_KILLS("mob_kills"),