2008-12-05 6 views
24

Tải DB trên trang web của tôi đang thực sự cao nên đã đến lúc tôi lưu trữ các truy vấn phổ biến được gọi là 1000 lần mỗi giờ mà kết quả không thay đổi. Vì vậy, ví dụ về mô hình thành phố của tôi, tôi làm như sau:Rails Caching DB Truy vấn và thực tiễn tốt nhất

def self.fetch(id) 
    Rails.cache.fetch("city_#{id}") { City.find(id) } 
end 

def after_save 
    Rails.cache.delete("city_#{self.id}") 
end 

def after_destroy 
    Rails.cache.delete("city_#{self.id}") 
end 

Vì vậy, bây giờ khi tôi có thể City.find (1) lần đầu tiên tôi nhấn DB nhưng 1000 lần tiếp theo tôi nhận được kết quả từ bộ nhớ. Tuyệt quá. Nhưng hầu hết các cuộc gọi đến thành phố không phải là City.find (1) nhưng @ user.city.name nơi Rails không sử dụng tìm nạp nhưng truy vấn DB một lần nữa ... điều đó có ý nghĩa nhưng không chính xác những gì tôi muốn nó làm.

Tôi có thể làm City.find (@ user.city_id) nhưng điều đó thật xấu.

Vì vậy, câu hỏi của tôi dành cho các bạn. Những người thông minh đang làm gì? cách phù hợp để thực hiện điều này là gì?

Trả lời

-1

Check-out cached_model

+0

memoization chỉ kết thúc tốt đẹp Rails.cache. Tôi không nghĩ rằng nó sẽ giúp mô hình hiệp hội như bạn đang tìm kiếm. – Bill

+1

Bản ghi nhớ không bao gồm bộ đệm Rails. Rails.cache thường là một kho lưu trữ cache được chia sẻ giữa các tiến trình (như vậy bạn thực sự có được các lợi ích bộ nhớ đệm). Việc ghi nhớ chỉ xảy ra trong quá trình hiện tại. – Michael

0

tôi sẽ đi trước và hãy nhìn vào Memoization, mà bây giờ trong Rails 2.2.

"Memoization là một mô hình của khởi tạo một phương pháp một lần và sau đó stashing giá trị của nó đi để chơi lại sử dụng."

Có một số lượng lớn Railscast episode trên thiết bị gần đây sẽ giúp bạn thiết lập và hoạt động tốt.

mẫu mã nhanh từ railscast:

class Product < ActiveRecord::Base 
    extend ActiveSupport::Memoizable 

    belongs_to :category 

    def filesize(num = 1) 
    # some expensive operation 
    sleep 2 
    12345789 * num 
    end 
    memoize :filesize 
end 

More on Memoization

+0

Lợi ích của việc ghi nhớ trên Rails.cache là gì và cách giải quyết vấn đề User.city.name nơi Rails thực hiện tìm kiếm trên Thành phố thay vì sử dụng dữ liệu được lưu trong bộ nhớ cache là gì? –

+9

Việc ghi nhớ sẽ chỉ lưu trữ kết quả trên cơ sở quy trình trên mỗi máy chủ và không làm mất hiệu lực, vì vậy việc này sẽ không phù hợp với hoàn cảnh của bạn và không được sử dụng theo cách này. – Michael

23

đối với bộ nhớ đệm, một vài điểm nhỏ Với:

Đó là giá trị sử dụng dấu gạch chéo để tách riêng các loại đối tượng và id , đó là quy ước đường ray. Thậm chí tốt hơn, các mô hình ActiveRecord cung cấp phương thức thể hiện cacke_key sẽ cung cấp mã nhận dạng duy nhất của tên bảng và id, "thành phố/13", v.v.

Một sửa đổi nhỏ cho bộ lọc after_save của bạn. Vì bạn có dữ liệu trong tay, bạn cũng có thể ghi nó trở lại bộ nhớ cache thay vì xóa nó. Đó là giúp bạn tiết kiệm một chuyến đi duy nhất để cơ sở dữ liệu;)

 
def after_save 
    Rails.cache.write(cache_key,self) 
end 

Như vào thư mục gốc của câu hỏi, nếu bạn đang liên tục kéo @ user.city.name, có hai sự lựa chọn thực tế:

  • Không chuẩn hóa tên thành phố của người dùng thành hàng của người dùng. @ user.city_name (giữ khóa ngoài city_id). Giá trị này nên được ghi vào lúc tiết kiệm thời gian.

-hoặc-

  • Thực hiện phương pháp User.fetch của bạn để tải háo hức thành phố. Chỉ thực hiện việc này nếu nội dung của hàng thành phố không bao giờ thay đổi (tức là tên, v.v.), nếu không bạn có khả năng mở một thùng sâu liên quan đến việc vô hiệu hóa bộ nhớ cache.

ý kiến ​​cá nhân: Thực hiện id cơ bản dựa lấy phương pháp (hoặc sử dụng một plugin) để tích hợp với memcached, và denormalize tên thành phố vào hàng của người dùng.

Cá nhân tôi không phải là một fan hâm mộ khổng lồ về các kiểu trình cắm kiểu mẫu được lưu trữ, tôi chưa bao giờ thấy một bộ lưu trữ một lượng thời gian phát triển đáng kể mà tôi đã không phát triển vội vàng.

Nếu bạn đang nhận được quá nhiều truy vấn cơ sở dữ liệu, nó chắc chắn đáng để kiểm tra mức tải mong muốn (thông qua: bao gồm) nếu bạn chưa có. Đó sẽ là bước đầu tiên để giảm số lượng truy vấn cơ sở dữ liệu.

+1

EG 'User.where (id: 3) .includes (: city) .first'. Được đánh giá thấp là 'tham gia hợp nhất' cho nhiều người đến nhiều mối quan hệ. EG 'City.joins (: nhà hàng) .merge (user.favorite_restaurants)', sẽ trả về tất cả các thành phố nơi người dùng có nhiều nhà hàng yêu thích và nhà hàng có nhiều thành phố. Kiểm tra [bao gồm và tham gia] (http://guides.rubyonrails.org/active_record_querying.html#joining-tables). Chắc chắn đáng giá để tìm hiểu làm thế nào để cắt giảm các cuộc gọi với các truy vấn mạnh mẽ hơn là đi qua những đau khổ của bộ nhớ đệm. –

0

Nếu bạn cần tăng tốc truy vấn sql trên dữ liệu không thay đổi nhiều theo thời gian thì bạn có thể sử dụng chế độ xem vật chất.

Matview lưu trữ kết quả truy vấn vào cấu trúc giống như bảng riêng của nó, từ đó dữ liệu có thể được truy vấn. Không thể thêm hoặc xóa các hàng, nhưng phần còn lại của thời gian hoạt động giống như một bảng thực tế . Truy vấn nhanh hơn và bản thân matview có thể được lập chỉ mục .

Tại thời điểm viết bài này, bản xem trước có sẵn trong Oracle DB, PostgreSQL, Sybase, IBM DB2 và Microsoft SQL Server. Tuy nhiên, MySQL không cung cấp hỗ trợ gốc cho xem trước, nhưng có là các lựa chọn thay thế nguồn mở cho nó.

Dưới đây là một số điều tốt về cách sử dụng matviews trong Rails

sitepoint.com/speed-up-with-materialized-views-on-postgresql-and-rails

hashrocket.com/materialized-view-strategies-using-postgresql