2011-01-15 3 views
5

Как я могу оптимизировать мои запросы SQL, чтобы игнорировать такие ситуации:counter_cache оптимизация has_many_through SQL, уменьшить количество SQL-запросов

Meeting.find (5) .users.size => SELECT COUNT (*) FROM ... WHERE ...

User.find (123) .meetings.size => SELECT COUNT (*) FROM ... WHERE ...

Я понятия не имею, как использовать counter_cache.

Вот моя модель отношение:

class Meeting < ActiveRecord::Base 
    has_many :meeting_users 
    has_many :users, :through => meeting_users 
end 

class User < ActiveRecord::Base 
    has_many :meeting_users 
    has_many :meetings, :through => meeting_users 
end 

class Meeting_user < ActiveRecord::Base 
    belongs_to :meeting 
    belongs_to :user 
end 

Каковы наиболее оптимальные решения?

И как реализовать counter_cache здесь?

+0

Может ли это что-то помешать вам сделать что-то вроде MeetingUser.where (: meeting_id => 5,: user_id => 123) .size для обеих ситуаций? По крайней мере, в этом случае вы сможете использовать кэширование SQL-запросов. Реализация counter_cache по умолчанию не поможет вам в такой ситуации. – jmcnevin

+1

Я думаю, вы ошибаетесь. counter_cache поможет здесь. Например, когда вы отображаете список пользователей в представлении, и вы будете отображать в каждой строке количество встреч каждого пользователя? С counter_cache это будет один SQL-запрос, без него будет 1 + n * Users.size – astropanic

ответ

1

Насколько я знаю, вы не можете использовать counter_cache с ассоциациями through, поэтому вы должны вручную увеличить его.

Например (непроверенных):

class MeetingUser < ActiveRecord::Base 

    ... 

    after_create { |record| 
    Meeting.increment_counter(:users_count, record.meeting.id) 
    } 

    after_destroy { |record| 
    Meeting.decrement_counter(:users_count, record.meeting.id) 
    } 

end 
22

Начиная с Rails3.0.5 и в более новых версиях, теперь вы можете установить кэш счетчика к модели «линкера», в вашем случае это будет:

class MeetingUser < ActiveRecord::Base 
    belongs_to :meeting, :counter_cache => :users_count 
    belongs_to :user, :counter_cache => :meetings_count 
end 

Важно четко указать имена столбцов счетчиков, иначе используемые столбцы будут по умолчанию равными meeting_users_count.

+0

Это сработало для меня. Меньше кода, чем решение after_create ... – tstyle

+0

Работает лучше для меня тоже! После создания события пропускаются по массовому назначению. Это должен быть принятый ответ. –

Смежные вопросы