徽章回填代码

我正在查看这里正在进行的徽章回填过程:

特别是,以下查询似乎存在一些问题(参见 https://meta.discourse.org/t/long-running-sidekiq-jobs/173974):

    sql = <<~SQL
      DELETE FROM user_badges
        WHERE id IN (
          SELECT ub.id
          FROM user_badges ub
          LEFT JOIN (
            #{badge.query}
          ) q ON q.user_id = ub.user_id
          #{post_clause}
          WHERE ub.badge_id = :id AND q.user_id IS NULL
        )
    SQL

该查询执行了 LEFT JOIN,因此无论是否有匹配项,都会返回 user_badges 中的所有结果,但这一部分似乎非常令人困惑:

ON q.user_id = ub.user_id
...
AND q.user_id IS NULL

该查询在 user_id 匹配的行上进行连接,但随后通过 WHERE 子句丢弃了这些行,使得这里的连接变得毫无意义。因此我想知道:

  1. 回填函数的目的是什么?它似乎完全清除了正在处理的徽章,然后一次性重新构建所有内容。这有必要吗?

  2. 针对帖子的徽章与不针对帖子的徽章在此函数方面有什么区别?使用 LEFT JOIN 时,在查找要清除以进行重建的正确 badge_id 时,这是否甚至重要?

3 个赞