From 6525613b89219036ebc461c48658b67e9ae7abbd Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Sat, 6 Apr 2019 07:55:24 +0800 Subject: [PATCH] PERF: Use joins for `Post.for_mailing_list` instead of `NOT IN`. Joining on the topics table and then filtering the topics against a large set of ids is so much slower than doing a join on a sub query. --- app/models/post.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index 8bca8c53df9..2a6ce5720c8 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -86,15 +86,16 @@ class Post < ActiveRecord::Base scope :with_topic_subtype, ->(subtype) { joins(:topic).where('topics.subtype = ?', subtype) } scope :visible, -> { joins(:topic).where('topics.visible = true').where(hidden: false) } scope :secured, -> (guardian) { where('posts.post_type IN (?)', Topic.visible_post_types(guardian&.user)) } + scope :for_mailing_list, ->(user, since) { q = created_since(since) - .joins(:topic) - .where(topic: Topic.for_digest(user, Time.at(0))) # we want all topics with new content, regardless when they were created + .joins("INNER JOIN (#{Topic.for_digest(user, Time.at(0)).select(:id).to_sql}) AS digest_topics ON digest_topics.id = posts.topic_id") # we want all topics with new content, regardless when they were created + .order('posts.created_at ASC') q = q.where.not(post_type: Post.types[:whisper]) unless user.staff? - - q.order('posts.created_at ASC') + q } + scope :raw_match, -> (pattern, type = 'string') { type = type&.downcase