From 883e2c32ce0aa9508f58f6b26be5b6b20fb277e2 Mon Sep 17 00:00:00 2001 From: Lex Cao Date: Tue, 21 Jun 2022 01:45:08 +0800 Subject: [PATCH] Fix slow deletion on `deleteClientSessionsByRealm` and `deleteClientSessionsByUser` when using mysql and mariadb by converting sub-query to join --- .../models/jpa/session/PersistentClientSessionEntity.java | 8 ++++++-- .../main/resources/META-INF/queries-default.properties | 8 ++++++++ .../main/resources/META-INF/queries-mariadb.properties | 6 ++++++ .../src/main/resources/META-INF/queries-mysql.properties | 6 ++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/session/PersistentClientSessionEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/session/PersistentClientSessionEntity.java index 3db3ccdb5932..62d5c7003dcf 100644 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/session/PersistentClientSessionEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/session/PersistentClientSessionEntity.java @@ -30,11 +30,15 @@ * @author Marek Posolda */ @NamedQueries({ - @NamedQuery(name="deleteClientSessionsByRealm", query="delete from PersistentClientSessionEntity sess where sess.userSessionId IN (select u.userSessionId from PersistentUserSessionEntity u where u.realmId = :realmId)"), + // sub-query with deletion performs very slow in MySQL/MariaDB databases + // It is removed from here and added manually in JpaUtils to give a native implementation if needed + // @NamedQuery(name="deleteClientSessionsByRealm", query="delete from PersistentClientSessionEntity sess where sess.userSessionId IN (select u.userSessionId from PersistentUserSessionEntity u where u.realmId = :realmId)"), @NamedQuery(name="deleteClientSessionsByClient", query="delete from PersistentClientSessionEntity sess where sess.clientId = :clientId"), @NamedQuery(name="deleteClientSessionsByExternalClient", query="delete from PersistentClientSessionEntity sess where sess.clientStorageProvider = :clientStorageProvider and sess.externalClientId = :externalClientId"), @NamedQuery(name="deleteClientSessionsByClientStorageProvider", query="delete from PersistentClientSessionEntity sess where sess.clientStorageProvider = :clientStorageProvider"), - @NamedQuery(name="deleteClientSessionsByUser", query="delete from PersistentClientSessionEntity sess where sess.userSessionId IN (select u.userSessionId from PersistentUserSessionEntity u where u.userId = :userId)"), + // sub-query with deletion performs very slow in MySQL/MariaDB databases + // It is removed from here and added manually in JpaUtils to give a native implementation if needed + // @NamedQuery(name="deleteClientSessionsByUser", query="delete from PersistentClientSessionEntity sess where sess.userSessionId IN (select u.userSessionId from PersistentUserSessionEntity u where u.userId = :userId)"), @NamedQuery(name="deleteClientSessionsByUserSession", query="delete from PersistentClientSessionEntity sess where sess.userSessionId = :userSessionId and sess.offline = :offline"), // KEYCLOAK-18842: The deleteExpiredClientSessions performs very slow in MySQL/MariaDB databases // It is removed from here and added manually in JpaUtils to give a native implementation if needed diff --git a/model/jpa/src/main/resources/META-INF/queries-default.properties b/model/jpa/src/main/resources/META-INF/queries-default.properties index a05c21ccd397..1759216dac37 100644 --- a/model/jpa/src/main/resources/META-INF/queries-default.properties +++ b/model/jpa/src/main/resources/META-INF/queries-default.properties @@ -8,3 +8,11 @@ deleteExpiredClientSessions=delete from PersistentClientSessionEntity sess where sess.userSessionId IN (\ select u.userSessionId from PersistentUserSessionEntity u \ where u.realmId = :realmId AND u.offline = :offline AND u.lastSessionRefresh < :lastSessionRefresh) + +deleteClientSessionsByRealm=delete from PersistentClientSessionEntity sess where sess.userSessionId IN (\ + select u.userSessionId from PersistentUserSessionEntity u \ + where u.realmId = :realmId) + +deleteClientSessionsByUser=delete from PersistentClientSessionEntity sess where sess.userSessionId IN (\ + select u.userSessionId from PersistentUserSessionEntity u \ + where u.userId = :userId) diff --git a/model/jpa/src/main/resources/META-INF/queries-mariadb.properties b/model/jpa/src/main/resources/META-INF/queries-mariadb.properties index be280c327627..cb3c69fdb125 100644 --- a/model/jpa/src/main/resources/META-INF/queries-mariadb.properties +++ b/model/jpa/src/main/resources/META-INF/queries-mariadb.properties @@ -7,3 +7,9 @@ deleteExpiredClientSessions[native]=delete c from OFFLINE_CLIENT_SESSION c join OFFLINE_USER_SESSION u \ where c.USER_SESSION_ID = u.USER_SESSION_ID and u.REALM_ID = :realmId and u.OFFLINE_FLAG = :offline \ and u.LAST_SESSION_REFRESH < :lastSessionRefresh + +deleteClientSessionsByRealm[native]=delete c from OFFLINE_CLIENT_SESSION c join OFFLINE_USER_SESSION u \ + where c.USER_SESSION_ID = u.USER_SESSION_ID and u.REALM_ID = :realmId + +deleteClientSessionsByUser[native]=delete c from OFFLINE_CLIENT_SESSION c join OFFLINE_USER_SESSION u \ + where c.USER_SESSION_ID = u.USER_SESSION_ID and u.USER_ID = :userId diff --git a/model/jpa/src/main/resources/META-INF/queries-mysql.properties b/model/jpa/src/main/resources/META-INF/queries-mysql.properties index be280c327627..cb3c69fdb125 100644 --- a/model/jpa/src/main/resources/META-INF/queries-mysql.properties +++ b/model/jpa/src/main/resources/META-INF/queries-mysql.properties @@ -7,3 +7,9 @@ deleteExpiredClientSessions[native]=delete c from OFFLINE_CLIENT_SESSION c join OFFLINE_USER_SESSION u \ where c.USER_SESSION_ID = u.USER_SESSION_ID and u.REALM_ID = :realmId and u.OFFLINE_FLAG = :offline \ and u.LAST_SESSION_REFRESH < :lastSessionRefresh + +deleteClientSessionsByRealm[native]=delete c from OFFLINE_CLIENT_SESSION c join OFFLINE_USER_SESSION u \ + where c.USER_SESSION_ID = u.USER_SESSION_ID and u.REALM_ID = :realmId + +deleteClientSessionsByUser[native]=delete c from OFFLINE_CLIENT_SESSION c join OFFLINE_USER_SESSION u \ + where c.USER_SESSION_ID = u.USER_SESSION_ID and u.USER_ID = :userId