mirror of
https://github.com/discourse/discourse.git
synced 2025-05-24 03:36:18 +08:00
PERF: Keep track of first unread PM and first unread group PM for user.
This optimization helps to filter away topics so that the joins on related tables when querying for unread messages is not expensive.
This commit is contained in:

committed by
Alan Guo Xiang Tan

parent
0398271f87
commit
9b75d95fc6
@ -12,10 +12,59 @@ class UserStat < ActiveRecord::Base
|
||||
update_distinct_badge_count
|
||||
update_view_counts(last_seen)
|
||||
update_first_unread(last_seen)
|
||||
update_first_unread_pm(last_seen)
|
||||
end
|
||||
|
||||
def self.update_first_unread(last_seen, limit: 10_000)
|
||||
DB.exec(<<~SQL, min_date: last_seen, limit: limit, now: 10.minutes.ago)
|
||||
UPDATE_UNREAD_MINUTES_AGO = 10
|
||||
UPDATE_UNREAD_USERS_LIMIT = 10_000
|
||||
|
||||
def self.update_first_unread_pm(last_seen, limit: UPDATE_UNREAD_USERS_LIMIT)
|
||||
DB.exec(<<~SQL, archetype: Archetype.private_message, now: UPDATE_UNREAD_MINUTES_AGO.minutes.ago, last_seen: last_seen, limit: limit)
|
||||
UPDATE user_stats us
|
||||
SET first_unread_pm_at = COALESCE(Z.min_date, :now)
|
||||
FROM (
|
||||
SELECT
|
||||
Y.user_id,
|
||||
Y.min_date
|
||||
FROM (
|
||||
SELECT
|
||||
u1.id user_id,
|
||||
X.min_date
|
||||
FROM users u1
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
tau.user_id,
|
||||
MIN(t.updated_at) min_date
|
||||
FROM topic_allowed_users tau
|
||||
INNER JOIN topics t ON t.id = tau.topic_id
|
||||
INNER JOIN users u ON u.id = tau.user_id
|
||||
LEFT JOIN topic_users tu ON t.id = tu.topic_id AND tu.user_id = tau.user_id
|
||||
WHERE t.deleted_at IS NULL
|
||||
AND t.archetype = :archetype
|
||||
AND tu.last_read_post_number < CASE
|
||||
WHEN u.admin OR u.moderator
|
||||
THEN t.highest_staff_post_number
|
||||
ELSE t.highest_post_number
|
||||
END
|
||||
AND (COALESCE(tu.notification_level, 1) >= 2)
|
||||
GROUP BY tau.user_id
|
||||
) AS X ON X.user_id = u1.id
|
||||
) AS Y
|
||||
WHERE Y.user_id IN (
|
||||
SELECT id
|
||||
FROM users
|
||||
WHERE last_seen_at IS NOT NULL
|
||||
AND last_seen_at > :last_seen
|
||||
ORDER BY last_seen_at DESC
|
||||
LIMIT :limit
|
||||
)
|
||||
) AS Z
|
||||
WHERE us.user_id = Z.user_id
|
||||
SQL
|
||||
end
|
||||
|
||||
def self.update_first_unread(last_seen, limit: UPDATE_UNREAD_USERS_LIMIT)
|
||||
DB.exec(<<~SQL, min_date: last_seen, limit: limit, now: UPDATE_UNREAD_MINUTES_AGO.minutes.ago)
|
||||
UPDATE user_stats us
|
||||
SET first_unread_at = COALESCE(Y.min_date, :now)
|
||||
FROM (
|
||||
|
Reference in New Issue
Block a user