From acae5af0adf3982cc66091ee52dc3d4083989583 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:40:59 +0000 Subject: [PATCH] core: optimize member subscriptions query (#6320) * core: optimize member subscriptions query * Revert "core: optimize member subscriptions query" This reverts commit a056cca6ccd7e420c13d8f93bf0dd4a4a2e8a345. * with materialized * plans --- src/Simplex/Chat/Store/Connections.hs | 27 +++--- .../SQLite/Migrations/agent_query_plans.txt | 4 + .../SQLite/Migrations/chat_query_plans.txt | 86 +++++++++++-------- 3 files changed, 69 insertions(+), 48 deletions(-) diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs index a270f95f1c..5a22ec4562 100644 --- a/src/Simplex/Chat/Store/Connections.hs +++ b/src/Simplex/Chat/Store/Connections.hs @@ -276,26 +276,29 @@ getMemberConnsToSub db User {userId, userContactId} filterToSubscribe = DB.query db query - ((userId, ConnDeleted, userContactId) - :. (GSMemRemoved, GSMemLeft, GSMemGroupDeleted, GSMemRemoved, GSMemLeft, GSMemGroupDeleted)) + ((userId, userContactId, GSMemRemoved, GSMemLeft, GSMemGroupDeleted) + :. (userId, ConnDeleted, GSMemRemoved, GSMemLeft, GSMemGroupDeleted)) where query - | filterToSubscribe = baseQuery <> " AND c.to_subscribe = 1 " <> cond - | otherwise = baseQuery <> " " <> cond + | filterToSubscribe = baseQuery <> " AND c.to_subscribe = 1" + | otherwise = baseQuery baseQuery = [sql| + WITH user_groups AS MATERIALIZED ( + SELECT g.group_id + FROM groups g + JOIN group_members mu ON mu.group_id = g.group_id + WHERE g.user_id = ? + AND mu.contact_id = ? + AND mu.member_status NOT IN (?,?,?) + ) SELECT c.agent_conn_id FROM connections c JOIN group_members m ON m.group_member_id = c.group_member_id - JOIN groups g ON g.group_id = m.group_id - JOIN group_members mu ON mu.group_id = g.group_id + JOIN user_groups ug ON ug.group_id = m.group_id WHERE c.user_id = ? - |] - cond = - [sql| - AND c.conn_status != ? - AND mu.contact_id = ? AND mu.member_status NOT IN (?,?,?) - AND m.member_status NOT IN (?,?,?) + AND c.conn_status != ? + AND m.member_status NOT IN (?,?,?) |] getPendingConnsToSub :: DB.Connection -> User -> Bool -> IO [ConnId] diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt b/src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt index 418ff56f48..7dd1835739 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt +++ b/src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt @@ -953,6 +953,10 @@ Plan: Query: INSERT INTO xftp_servers (xftp_host, xftp_port, xftp_key_hash) VALUES (?,?,?) Plan: +Query: SELECT 1 FROM connections WHERE conn_id = ? AND deleted_at_wait_delivery < ? LIMIT 1 +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + Query: SELECT 1 FROM encrypted_rcv_message_hashes WHERE conn_id = ? AND hash = ? LIMIT 1 Plan: SEARCH encrypted_rcv_message_hashes USING COVERING INDEX idx_encrypted_rcv_message_hashes_hash (conn_id=? AND hash=?) diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt b/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt index cc725d96a7..be8e7fe244 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt +++ b/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt @@ -3167,42 +3167,6 @@ Plan: SEARCH c USING INDEX idx_connections_to_subscribe (user_id=? AND to_subscribe=?) SEARCH ct USING INTEGER PRIMARY KEY (rowid=?) -Query: - SELECT c.agent_conn_id - FROM connections c - JOIN group_members m ON m.group_member_id = c.group_member_id - JOIN groups g ON g.group_id = m.group_id - JOIN group_members mu ON mu.group_id = g.group_id - WHERE c.user_id = ? - - AND c.conn_status != ? - AND mu.contact_id = ? AND mu.member_status NOT IN (?,?,?) - AND m.member_status NOT IN (?,?,?) - -Plan: -SEARCH c USING INDEX idx_connections_to_subscribe (user_id=?) -SEARCH m USING INTEGER PRIMARY KEY (rowid=?) -SEARCH g USING INTEGER PRIMARY KEY (rowid=?) -SEARCH mu USING INDEX sqlite_autoindex_group_members_1 (group_id=?) - -Query: - SELECT c.agent_conn_id - FROM connections c - JOIN group_members m ON m.group_member_id = c.group_member_id - JOIN groups g ON g.group_id = m.group_id - JOIN group_members mu ON mu.group_id = g.group_id - WHERE c.user_id = ? - AND c.to_subscribe = 1 - AND c.conn_status != ? - AND mu.contact_id = ? AND mu.member_status NOT IN (?,?,?) - AND m.member_status NOT IN (?,?,?) - -Plan: -SEARCH c USING INDEX idx_connections_to_subscribe (user_id=? AND to_subscribe=?) -SEARCH m USING INTEGER PRIMARY KEY (rowid=?) -SEARCH g USING INTEGER PRIMARY KEY (rowid=?) -SEARCH mu USING INDEX sqlite_autoindex_group_members_1 (group_id=?) - Query: SELECT c.agent_conn_id FROM connections c @@ -3884,6 +3848,56 @@ Query: Plan: SEARCH groups USING INTEGER PRIMARY KEY (rowid=?) +Query: + WITH user_groups AS MATERIALIZED ( + SELECT g.group_id + FROM groups g + JOIN group_members mu ON mu.group_id = g.group_id + WHERE g.user_id = ? + AND mu.contact_id = ? + AND mu.member_status NOT IN (?,?,?) + ) + SELECT c.agent_conn_id + FROM connections c + JOIN group_members m ON m.group_member_id = c.group_member_id + JOIN user_groups ug ON ug.group_id = m.group_id + WHERE c.user_id = ? + AND c.conn_status != ? + AND m.member_status NOT IN (?,?,?) + +Plan: +MATERIALIZE user_groups +SEARCH mu USING INDEX idx_group_members_contact_id (contact_id=?) +SEARCH g USING INTEGER PRIMARY KEY (rowid=?) +SEARCH c USING INDEX idx_connections_to_subscribe (user_id=?) +SEARCH m USING INTEGER PRIMARY KEY (rowid=?) +SEARCH ug USING AUTOMATIC COVERING INDEX (group_id=?) + +Query: + WITH user_groups AS MATERIALIZED ( + SELECT g.group_id + FROM groups g + JOIN group_members mu ON mu.group_id = g.group_id + WHERE g.user_id = ? + AND mu.contact_id = ? + AND mu.member_status NOT IN (?,?,?) + ) + SELECT c.agent_conn_id + FROM connections c + JOIN group_members m ON m.group_member_id = c.group_member_id + JOIN user_groups ug ON ug.group_id = m.group_id + WHERE c.user_id = ? + AND c.conn_status != ? + AND m.member_status NOT IN (?,?,?) + AND c.to_subscribe = 1 +Plan: +MATERIALIZE user_groups +SEARCH mu USING INDEX idx_group_members_contact_id (contact_id=?) +SEARCH g USING INTEGER PRIMARY KEY (rowid=?) +SEARCH c USING INDEX idx_connections_to_subscribe (user_id=? AND to_subscribe=?) +SEARCH m USING INTEGER PRIMARY KEY (rowid=?) +SEARCH ug USING AUTOMATIC COVERING INDEX (group_id=?) + Query: DELETE FROM chat_items WHERE group_scope_group_member_id = ?