Rails - 连接表上查询的索引

时间:2012-05-08 12:32:54

标签: mysql ruby-on-rails indexing

在我的应用文章中,文章通过自引用加入模型article_relationships

有很多孩子或父文章
class Article < ActiveRecord::Base

  has_many  :parent_child_relationships,
            :class_name   => "ArticleRelationship",
            :foreign_key  => :child_id,
            :dependent    => :destroy
  has_many  :parents,
            :through    => :parent_child_relationships,
            :source     => :parent

  has_many  :child_parent_relationships,
            :class_name   => "ArticleRelationship",
            :foreign_key  => :parent_id,
            :dependent    => :destroy
  has_many  :children,
            :through    => :child_parent_relationships,
            :source     => :child
end

class ArticleRelationship < ActiveRecord::Base
  belongs_to :parent, :class_name => "Article"
  belongs_to :child, :class_name => "Article"
end

我对article_relationships有一个相当复杂的查询,深入到文章表

ArticleRelationship.joins(:parent, :child).where("((articles.type IN (:parent_article_type) AND parent_id IN (:ids)) OR (children_article_relationships.type IN (:child_article_type) AND child_id IN (:ids)) AND (article_relationships.created_at > :date OR article_relationships.updated_at > :date))", {:parent_article_type => "Emotion", :child_article_type => "Gateway", :ids => [1,2,3,4], :date => "2010-01-01"})

有没有办法可以有效地索引这个?

1 个答案:

答案 0 :(得分:0)

所以,只是为了便于阅读,

ArticleRelationship.joins(:parent, :child).
 where("((articles.type IN (:parent_article_type) AND parent_id IN (:ids)) OR
         (children_article_relationships.type IN (:child_article_type) AND child_id IN (:ids))
        AND (article_relationships.created_at > :date OR article_relationships.updated_at > :date))",
       { :parent_article_type => "Emotion",
         :child_article_type => "Gateway",
         :ids => [1,2,3,4], :date => "2010-01-01" })

问题是OR运算符。由于OR,在两个顶级AND表达式中,数据库都不能使用索引。

  1. 因为,当创建记录时,它还将updated_at字段设置为相同的时间戳,您可以删除OR created_at,允许您在update_at上建立索引。
  2. 如果您可以按文章类型过滤父ID和子ID,则可以删除这些OR。但是,请确保您可以有效地执行此操作,以便不会花费更多时间将id列表作为输入进行过滤,它不会比未编入索引的查询花费更长的时间。首先尝试1.然后查看updated_at索引需要多长时间。
  3. 如果同时执行1和2,请确保创建一个包含所有三个字段的索引,updated_at,parent_id和child_id。