OPTIM: change Top Topic's score computation algorithm

New algorithm will not wipe the entire table anymore and will only remove
invisible topics and add new visible topics.
This commit is contained in:
Régis Hanol 2014-02-28 20:33:52 +01:00
parent 5e1019adba
commit 6b83ed0347
3 changed files with 44 additions and 38 deletions

View File

@ -1,19 +0,0 @@
require_dependency 'score_calculator'
module Jobs
# This job will run on a regular basis to update statistics and denormalized data.
# If it does not run, the site will not function properly.
class Daily < Jobs::Scheduled
every 1.day
def execute(args)
# TODO: optimise this against a big site before doing this any more
# frequently
#
# current implementation wipes an entire table and rebuilds causing huge
# amounts of IO
TopTopic.refresh!
end
end
end

View File

@ -21,6 +21,9 @@ module Jobs
# Update the scores of posts
ScoreCalculator.new.calculate(1.day.ago)
# Update the scores of topics
TopTopic.refresh!
# Automatically close stuff that we missed
Topic.auto_close
end

View File

@ -12,20 +12,11 @@ class TopTopic < ActiveRecord::Base
def self.refresh!
transaction do
# clean up the table
exec_sql("DELETE FROM top_topics")
# insert the list of all the visible topics
exec_sql("INSERT INTO top_topics (topic_id)
SELECT id
FROM topics
WHERE deleted_at IS NULL
AND visible
AND archetype <> :private_message
AND NOT archived",
private_message: Archetype::private_message)
# update the topics list
remove_invisible_topics
add_new_visible_topics
# update the denormalized data
TopTopic.periods.each do |period|
# update all the counter caches
TopTopic.sort_orders.each do |sort|
TopTopic.send("update_#{sort}_count_for", period)
end
@ -35,14 +26,45 @@ class TopTopic < ActiveRecord::Base
end
end
def self.remove_invisible_topics
exec_sql("WITH invisible_topics AS (
SELECT id
FROM topics
WHERE deleted_at IS NOT NULL
OR NOT visible
OR archetype = :private_message
OR archived
)
DELETE FROM top_topics
WHERE topic_id IN (SELECT id FROM invisible_topics)",
private_message: Archetype::private_message)
end
def self.add_new_visible_topics
exec_sql("WITH visible_topics AS (
SELECT t.id
FROM topics t
LEFT JOIN top_topics tt ON t.id = tt.topic_id
WHERE t.deleted_at IS NULL
AND t.visible
AND t.archetype <> :private_message
AND NOT t.archived
AND tt.topic_id IS NULL
)
INSERT INTO top_topics (topic_id)
SELECT id
FROM visible_topics",
private_message: Archetype::private_message)
end
def self.update_posts_count_for(period)
sql = "SELECT topic_id, GREATEST(COUNT(*), 1) AS count
FROM posts
WHERE created_at >= :from
AND deleted_at IS NULL
AND NOT hidden
AND post_type = #{Post.types[:regular]}
AND user_id <> #{Discourse.system_user.id}
AND deleted_at IS NULL
AND NOT hidden
AND post_type = #{Post.types[:regular]}
AND user_id <> #{Discourse.system_user.id}
GROUP BY topic_id"
TopTopic.update_top_topics(period, "posts", sql)
@ -61,8 +83,8 @@ class TopTopic < ActiveRecord::Base
sql = "SELECT topic_id, GREATEST(SUM(like_count), 1) AS count
FROM posts
WHERE created_at >= :from
AND deleted_at IS NULL
AND NOT hidden
AND deleted_at IS NULL
AND NOT hidden
GROUP BY topic_id"
TopTopic.update_top_topics(period, "likes", sql)