From 4d00e8a56e6e50ea7a887f50ede3af4c92e88a7f Mon Sep 17 00:00:00 2001 From: gsd Date: Sun, 26 Jul 2026 15:45:23 +0300 Subject: [PATCH] db optimize 2 --- src/main/java/app/entities/SearchFilter.java | 2 +- .../app/repositories/KillfeedRepository.java | 14 +-- .../java/app/services/db/KillfeedService.java | 8 +- .../java/app/services/db/UsertimeService.java | 92 +++++++++++++++++-- 4 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/main/java/app/entities/SearchFilter.java b/src/main/java/app/entities/SearchFilter.java index 1771d58..64aa2ba 100644 --- a/src/main/java/app/entities/SearchFilter.java +++ b/src/main/java/app/entities/SearchFilter.java @@ -121,7 +121,7 @@ public class SearchFilter { } public String getServerId() { - return serverId == null || serverId.isEmpty() ? null : serverId; + return serverId == null || serverId.isEmpty() || serverId.contains("%") ? null : serverId; } /** diff --git a/src/main/java/app/repositories/KillfeedRepository.java b/src/main/java/app/repositories/KillfeedRepository.java index b131b6e..5757258 100644 --- a/src/main/java/app/repositories/KillfeedRepository.java +++ b/src/main/java/app/repositories/KillfeedRepository.java @@ -14,7 +14,7 @@ public interface KillfeedRepository extends PagingAndSortingRepository= :utime) and " + - "(:server_id is null or k.server_id like :server_id) and" + + "(:server_id is null or k.server_id = :server_id) and" + "(:account_id is null or (k.attacker_id = :account_id and k.attacker_id != k.victim_id))") Long getKills( @Param("account_id") Long account_id, @@ -24,7 +24,7 @@ public interface KillfeedRepository extends PagingAndSortingRepository= :begin_date) and " + "(:end_date is null or :end_date >= k.utime) and " + - "(:server_id is null or k.server_id like :server_id) and" + + "(:server_id is null or k.server_id = :server_id) and" + "(:accounts_id_non_exists = true or (k.attacker_id in :accounts_id and k.attacker_id != k.victim_id)) order by k.id desc") Page getKills(Pageable pageable, @Param("accounts_id_non_exists") boolean accounts_id_non_exists, @@ -36,7 +36,7 @@ public interface KillfeedRepository extends PagingAndSortingRepository= :utime) and " + - "(:server_id is null or k.server_id like :server_id) and" + + "(:server_id is null or k.server_id = :server_id) and" + "(:account_id is null or (k.victim_id = :account_id and k.attacker_id != k.victim_id))") Long getDeads( @Param("account_id") Long account_id, @@ -46,7 +46,7 @@ public interface KillfeedRepository extends PagingAndSortingRepository= :begin_date) and " + "(:end_date is null or :end_date >= k.utime) and " + - "(:server_id is null or k.server_id like :server_id) and" + + "(:server_id is null or k.server_id = :server_id) and" + "(:accounts_id_non_exists = true or (k.victim_id in :accounts_id and k.attacker_id != k.victim_id)) order by k.id desc") Page getDeads(Pageable pageable, @Param("accounts_id_non_exists") boolean accounts_id_non_exists, @@ -58,7 +58,7 @@ public interface KillfeedRepository extends PagingAndSortingRepository= :utime) and " + - "(:server_id is null or k.server_id like :server_id) and" + + "(:server_id is null or k.server_id = :server_id) and" + "(:account_id is null or (k.victim_id = :account_id and k.attacker_id = k.victim_id))") Long getSuicides( @Param("account_id") Long account_id, @@ -69,7 +69,7 @@ public interface KillfeedRepository extends PagingAndSortingRepository= :utime) and " + - "(:server_id is null or k.server_id like :server_id) and" + + "(:server_id is null or k.server_id = :server_id) and" + "(:account_id is null or k.assister_id = :account_id)") Long getAssists( @Param("account_id") Long account_id, @@ -79,7 +79,7 @@ public interface KillfeedRepository extends PagingAndSortingRepository= :begin_date) and " + "(:end_date is null or :end_date >= k.utime) and " + - "(:server_id is null or k.server_id like :server_id) and" + + "(:server_id is null or k.server_id = :server_id) and" + "(:accounts_id_non_exists = true or k.assister_id in :accounts_id) order by k.id desc") Page getAssists(Pageable pageable, @Param("accounts_id_non_exists") boolean accounts_id_non_exists, diff --git a/src/main/java/app/services/db/KillfeedService.java b/src/main/java/app/services/db/KillfeedService.java index c7cb81a..534b6ce 100644 --- a/src/main/java/app/services/db/KillfeedService.java +++ b/src/main/java/app/services/db/KillfeedService.java @@ -54,7 +54,7 @@ public class KillfeedService { public List getTopKills(String server_id) { return jdbcTemplate.query("SELECT attacker_id, count(*) as c, server_id " + "FROM user_killfeed " + - "WHERE victim_id != attacker_id AND attacker_id != 0 AND (? =0 or server_id LIKE ?) " + + "WHERE victim_id != attacker_id AND attacker_id != 0 AND (? = 0 or server_id = ?) " + "GROUP BY attacker_id, server_id " + "ORDER BY c DESC LIMIT 10", new Object[]{ @@ -68,7 +68,7 @@ public class KillfeedService { public List getTopDeads(String server_id) { return jdbcTemplate.query("SELECT victim_id, count(id) as c, server_id " + "FROM user_killfeed " + - "WHERE victim_id != attacker_id AND victim_id != 0 AND (? =0 or server_id LIKE ?) " + + "WHERE victim_id != attacker_id AND victim_id != 0 AND (? = 0 or server_id = ?) " + "GROUP BY victim_id, server_id " + "ORDER BY c DESC LIMIT 10", new Object[]{ @@ -83,13 +83,13 @@ public class KillfeedService { List result = jdbcTemplate.query("SELECT COUNT(u.weapon_index) as c, i.name, u.server_id, u.weapon_classname " + "FROM user_killfeed as u " + "INNER JOIN tf2idb.tf2idb_item as i ON u.weapon_index = i.id " + - "WHERE u.attacker_id = ? AND attacker_id != victim_id AND (? =0 or u.server_id like ?) " + + "WHERE u.attacker_id = ? AND attacker_id != victim_id AND (? = 0 or u.server_id = ?) " + "GROUP BY u.weapon_index, i.name, u.server_id, u.weapon_classname " + "ORDER BY c DESC LIMIT ? OFFSET ?", new Object[]{ steamID.account_id, server_id == null || server_id.isEmpty() ? 0 : 1, - server_id==null||server_id.isEmpty()?"%":server_id, + server_id == null || server_id.isEmpty() ? "%" :server_id, limit, offset }, (rs, n) -> new HypeWeapons(rs)); diff --git a/src/main/java/app/services/db/UsertimeService.java b/src/main/java/app/services/db/UsertimeService.java index d5e1bb5..0815d60 100644 --- a/src/main/java/app/services/db/UsertimeService.java +++ b/src/main/java/app/services/db/UsertimeService.java @@ -5,6 +5,8 @@ import app.entities.other.SteamID; import app.entities.server.Server; import app.entities.Stats; import app.utils.SteamIDConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; @@ -27,6 +29,7 @@ public class UsertimeService { //Лучше это всегда держать в true private boolean last_map = true; private Stats stats; + private static final Logger logger = LoggerFactory.getLogger(UsertimeService.class); @Autowired public UsertimeService(Stats stats) { @@ -88,28 +91,42 @@ public class UsertimeService { } public Timestamp getLastplay(String server_id, SteamID steamID, String map) { - return jdbcTemplate.query("select timestamp from user_connections WHERE srv_id like ? AND map LIKE ? and connection_type LIKE ? AND account_id = ? ORDER BY user_connections.id DESC LIMIT 1", - new Object[]{ server_id, map, "disconnect", steamID.account_id}, + if (server_id == null || server_id.isEmpty() || steamID == null || map == null) { + logger.warn("Cannot fetch lastplay, req values is null"); + return null; + } + + return jdbcTemplate.query("select timestamp from user_connections WHERE account_id = ? AND srv_id = ? AND map = ? and connection_type = ? ORDER BY user_connections.id DESC LIMIT 1", + new Object[]{steamID.account_id, server_id, map, "disconnect"}, (rs, n) -> rs.getTimestamp("timestamp")) .stream().findFirst().orElse(null); } public BigDecimal getTotalPlaytime(String server_id, SteamID steamID, String map) { - List l = jdbcTemplate.query("select sum(connect_duration) as total from user_connections WHERE srv_id like ? AND map LIKE ? and connection_type LIKE ? AND account_id = ?", - new Object[]{ server_id, map, "disconnect", steamID.account_id }, + if (server_id == null || server_id.isEmpty() || steamID == null || map == null) { + logger.warn("Cannot fetch totalplaytime, req values is null"); + return null; + } + + List l = jdbcTemplate.query("select sum(connect_duration) as total from user_connections WHERE account_id = ? AND srv_id = ? AND map = ? and connection_type = ?", + new Object[]{ steamID.account_id, server_id, map, "disconnect" }, (rs, n) -> rs.getBigDecimal("total")); //optional if has error return l.size() > 0?l.get(0):null; } public List getMap(String server_id, int limit) { - return jdbcTemplate.query("select map from user_connections WHERE srv_id like ? group by map, id ORDER BY user_connections.id DESC LIMIT ?", + if (server_id == null || server_id.isEmpty() || server_id.contains("%")) { + logger.warn("Get map use wildcard or null srv_id"); + } + + return jdbcTemplate.query("select map from user_connections WHERE srv_id = ? group by map, id ORDER BY user_connections.id DESC LIMIT ?", new Object[]{ server_id, limit }, (rs, n) -> rs.getString("map")); } public List getMaps(String server_id) { - return jdbcTemplate.query("select map from user_connections where srv_id like ? group by map", + return jdbcTemplate.query("select map from user_connections where srv_id = ? group by map", new Object[]{server_id}, (rs, n) -> rs.getString("map")); } @@ -122,15 +139,70 @@ public class UsertimeService { } public List getGametimeOnServer(SteamID steamID, String server, Integer limit, Integer offset) { - return jdbcTemplate.query("SELECT * FROM user_connections WHERE srv_id like ? and account_id = ? AND connection_type LIKE ? ORDER BY user_connections.id DESC LIMIT ? OFFSET ?", - new Object[]{ server, steamID.account_id, "disconnect", limit, offset}, + int any_server = 0; + if (server == null || server.isEmpty() || server.contains("%")) + any_server = 1; + + return jdbcTemplate.query("SELECT * FROM user_connections WHERE account_id = ? and (? = 1 or srv_id = ?) AND connection_type = ? ORDER BY user_connections.id DESC LIMIT ? OFFSET ?", + new Object[]{ steamID.account_id, any_server, server, "disconnect", limit, offset}, (rs, n) -> new Gametime(rs)); } public Long getTotalGametimeOnServer(SteamID steamID, String server) { - return jdbcTemplate.query("SELECT count(id) FROM user_connections WHERE srv_id like ? and account_id = ? AND connection_type LIKE ?", - new Object[]{ server, steamID.account_id, "disconnect" }, + int any_server = 0; + if (server == null || server.isEmpty() || server.contains("%")) + any_server = 1; + + return jdbcTemplate.query("SELECT count(id) FROM user_connections WHERE account_id = ? AND (? = 1 or srv_id = ?) and connection_type = ?", + new Object[]{ steamID.account_id, any_server, server, "disconnect" }, (rs, n) -> rs.getLong(1)) .stream().findFirst().orElse(0L); } + + /* + WITH ordered AS ( + SELECT + id, + account_id, + timestamp, + connection_type, + srv_id, + connect_duration, + ROW_NUMBER() OVER (PARTITION BY account_id ORDER BY timestamp, id) AS rn + FROM tf2_facti13.user_connections + WHERE account_id = 127332962 + ), + paired AS ( + SELECT + c.account_id, + c.timestamp AS session_start, + d.timestamp AS session_end, + c.id AS connect_id, + d.id AS disconnect_id, + c.srv_id AS server_id, + EXTRACT(EPOCH FROM (d.timestamp - c.timestamp)) AS delta_in_seconds, + d.connect_duration as cd, + -- Нумеруем сессии для каждого пользователя по времени начала + ROW_NUMBER() OVER (PARTITION BY c.account_id ORDER BY c.timestamp) AS session_number + FROM ordered c + JOIN ordered d + ON c.account_id = d.account_id + AND c.rn + 1 = d.rn + WHERE c.connection_type = 'connect' + AND d.connection_type = 'disconnect' + AND c.srv_id = d.srv_id -- сессия на одном сервере + ) + SELECT + session_number, + account_id, + session_start, + session_end, + delta_in_seconds, + cd, + connect_id, + disconnect_id, + server_id + FROM paired + ORDER BY session_number desc; + */ }