mirror of
https://github.com/discourse/discourse.git
synced 2026-08-03 09:53:24 -05:00
PERF: Keep track of when a users first unread is
This optimisation avoids large scans joining the topics table with the topic_users table. Previously when a user carried a lot of read state we would have to join the entire read state with the topics table. This operation would slow down home page and every topic page. The more read state you accumulated the larger the impact. The optimisation helps people who clean up unread, however if you carry unread from years ago it will only have minimal impact.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
class AddFirstUnreadAtToUserStats < ActiveRecord::Migration[5.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
# so we can rerun this if the index creation fails out of ddl
|
||||
if !column_exists?(:user_stats, :first_unread_at)
|
||||
add_column :user_stats, :first_unread_at, :datetime, null: false, default: -> { 'CURRENT_TIMESTAMP' }
|
||||
end
|
||||
|
||||
execute <<~SQL
|
||||
UPDATE user_stats us
|
||||
SET first_unread_at = u.created_at
|
||||
FROM users u
|
||||
WHERE u.id = us.user_id
|
||||
SQL
|
||||
|
||||
# this is quite a big index to carry, but we need it to optimise home page initial load
|
||||
# by covering all these columns we are able to quickly retrieve the set of topics that were
|
||||
# updated in the last N days. We perform a ranged lookup and selectivity may vary a lot
|
||||
add_index :topics,
|
||||
[:updated_at, :visible, :highest_staff_post_number, :highest_post_number, :category_id, :created_at, :id],
|
||||
algorithm: :concurrently,
|
||||
name: 'index_topics_on_updated_at_public',
|
||||
where: "(topics.archetype <> 'private_message') AND (topics.deleted_at IS NULL)"
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user