2011-01-15 36 views
5

Làm thế nào tôi có thể tối ưu hóa các truy vấn SQL của tôi, để bỏ qua những tình huống như thế này:counter_cache has_many_through sql tối ưu hóa, làm giảm số lượng các truy vấn SQL

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

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

tôi không có ý tưởng làm thế nào để sử dụng counter_cache ở đây.

Đây là mối quan hệ mô hình của tôi:

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 

các giải pháp tối ưu nhất là gì?

Và cách thực hiện counter_cache tại đây?

+0

Mọi thứ ở đây có ngăn cản bạn thực hiện điều gì đó như MeetingUser.where (: meeting_id => 5,: user_id => 123) .size cho cả hai trường hợp? Ít nhất trong trường hợp đó bạn sẽ có thể tận dụng bộ nhớ đệm truy vấn SQL. Việc thực thi mặc định của counter_cache sẽ không thực sự giúp bạn trong tình huống này. – jmcnevin

+1

Tôi nghĩ bạn sai. counter_cache sẽ trợ giúp ở đây. Ví dụ: Khi bạn hiển thị danh sách người dùng trong chế độ xem và Bạn sẽ hiển thị trong mỗi dòng có bao nhiêu cuộc họp mà mỗi người dùng có? Với counter_cache đây sẽ là một truy vấn SQL, không có nó sẽ là 1 + n * Users.size – astropanic

Trả lời

1

Theo như tôi biết bạn không thể sử dụng counter_cache với các liên kết through, đó là lý do tại sao bạn nên tăng thủ công.

Ví dụ (chưa được kiểm tra):

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

Bắt đầu từ Rails3.0.5 và trong các phiên bản mới hơn, bây giờ bạn có thể thiết lập truy cập bộ nhớ cache để mô hình "liên kết", trong trường hợp của bạn nó sẽ là:

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

Điều quan trọng là chỉ định rõ tên cột, nếu không cột được sử dụng sẽ mặc định là meeting_users_count.

+0

Điều này làm việc cho tôi. Ít mã hơn giải pháp after_create ... – tstyle

+0

Hoạt động tốt hơn cho tôi! Sau khi tạo các sự kiện sẽ bị bỏ qua khi gán hàng loạt. Đây sẽ là câu trả lời được chấp nhận. –

Các vấn đề liên quan