subscription_info: Improve subscriber fetch preformance.

Discussed here:
https://chat.zulip.org/#narrow/channel/141-kandra-ops/topic/partial.20subscribers.20query.20does.20users.20sequential.20scan/near/2255421
This commit is contained in:
Evy Kassirer
2025-09-05 11:18:18 -07:00
committed by Tim Abbott
parent 74b07740b0
commit 31505e90f7

View File

@@ -603,32 +603,54 @@ def bulk_get_subscriber_user_ids(
20k+ total subscribers. (For large realms with lots of default
streams, this function deals with LOTS of data, so it is important
to optimize.)
One optimization is to use two branches for creating this query,
to avoid joining on zerver_userprofile when we're not sending
partial users.
"""
query = SQL(
"""
SELECT
zerver_subscription.recipient_id,
zerver_subscription.user_profile_id
FROM
zerver_subscription
JOIN zerver_userprofile on zerver_userprofile.id = zerver_subscription.user_profile_id
WHERE
zerver_subscription.active AND
zerver_subscription.is_user_active AND
(
zerver_subscription.recipient_id = ANY (%(full_fetch_recipient_ids)s)
OR
if partial_fetch_recipient_ids:
query = SQL(
"""
SELECT
zerver_subscription.recipient_id,
zerver_subscription.user_profile_id
FROM
zerver_subscription
JOIN zerver_userprofile on zerver_userprofile.id = zerver_subscription.user_profile_id
WHERE
zerver_subscription.active AND
zerver_subscription.is_user_active AND
(
zerver_subscription.recipient_id = ANY (%(partial_fetch_recipient_ids)s) AND
(zerver_userprofile.is_bot OR (NOT zerver_userprofile.long_term_idle))
zerver_subscription.recipient_id = ANY (%(full_fetch_recipient_ids)s)
OR
(
zerver_subscription.recipient_id = ANY (%(partial_fetch_recipient_ids)s) AND
(zerver_userprofile.is_bot OR (NOT zerver_userprofile.long_term_idle))
)
)
)
ORDER BY
zerver_subscription.recipient_id,
zerver_subscription.user_profile_id
"""
)
ORDER BY
zerver_subscription.recipient_id,
zerver_subscription.user_profile_id
"""
)
else:
query = SQL(
"""
SELECT
zerver_subscription.recipient_id,
zerver_subscription.user_profile_id
FROM
zerver_subscription
WHERE
zerver_subscription.active AND
zerver_subscription.is_user_active AND
zerver_subscription.recipient_id = ANY (%(full_fetch_recipient_ids)s)
ORDER BY
zerver_subscription.recipient_id,
zerver_subscription.user_profile_id
"""
)
cursor = connection.cursor()
cursor.execute(