慢查询联接表

时间:2019-05-21 12:55:03

标签: mysql ruby-on-rails

我正在尝试优化以下查询:

有两个表,Post(> 100万条记录)和Category(约10-20条记录)。

查询应检索posts分别为1和2的所有category_idposts_categories和{{的联接表post_id都有索引1}},并解释说明确认查询中正在使用索引。

但是,查询仍然很慢。似乎是造成这种情况的原因所在。

赞赏一些改进建议。

category_id
Post
   .joins(:categories)
   .where(categories: { id: [1,2] })
   .group(:post_id) 
   .having("COUNT(categories.id) = 2")

2 个答案:

答案 0 :(得分:3)

这可能不起作用,但是值得一试。

您可以尝试编写子查询以获取类别ID。

您需要在PostsCategories连接表上编写一个简单的ActiveRecord模型...

Post
  .where(id: PostCategory.where(category_id: [1,2]).select(:post_id))
  .joins(:post_categories)
  .group(:post_id) 
  .having("COUNT(post_category.category_id)=2")

因此,这里的优势:

  • 您不再通过联接表联接到大型“类别”表。
  • 子查询允许数据库仅选择具有这些类别ID的PostCategories,从而缩小该字段的范围。

答案 1 :(得分:0)

对不起,请尝试另一件事。

我不确定您是否可以在ActiveRecord中编写此代码,要将其转换为纯AREL非常复杂,因此,这里有一个变通办法,可能会帮您解决问题。

Post.find_by_sql(
  "
    select * from posts where id in (
      SELECT cp1.post_id FROM JOIN categories_posts cp1
      INNER JOIN categories_posts cp2 ON cp1.post_id = cp2.post_id
      where cp1.category_id = 1 and cp2.category_id = 2
    )
  "
)

要考虑的另一件事是分页,您可以尝试添加类似这样的内容,以便仅查看帖子的一部分:

and cp1.post_id between 1 and 10000

(在Oracle上经过测试,可能存在一些语法差异)