2008-12-05 55 views
24

我的網站上的數據庫負載變得非常高,因此我需要緩存常見查詢,這些查詢在結果不變的情況下被稱爲每小時1000次。 因此,例如在我的城市模型我做到以下幾點:Rails緩存數據庫查詢和最佳實踐

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 

所以現在當我可以City.find(1)我第一次打DB但接下來的1000次我從記憶的結果。大。但是大多數城市呼叫不是City.find(1),而是@ user.city.name,其中Rails不使用抓取,而是再次查詢數據庫......這是有道理的,但不是我想要的。

我可以做City.find(@ user.city_id)但這很醜。

所以我的問題給你們。聰明人在做什麼?什麼是 正確的方法來做到這一點?

回答

-1

退房cached_model

+0

記憶化只是包裝的Rails.cache一些好文章。我認爲這不會幫助您尋找的模特協會。 – Bill 2008-12-05 22:57:15

+1

Memoization不包裝Rails緩存。 Rails.cache通常是進程之間共享的緩存存儲(這樣您實際獲得緩存優勢)。記憶只發生在當前過程中。 – Michael 2008-12-06 05:39:17

0

我會繼續前進,看看Memoization,這是現在在Rails的2.2。

「記憶化是 初始化方法一次,然後 積攢其值離開重複 使用的圖案。」

最近有一個偉大的Railscast episode,應該讓你很好地運行。從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

對Rails.cache進行memoization的好處是什麼,以及如何解決User.city.name的問題,Rails在City上查找而不是使用緩存數據? – 2008-12-05 21:26:27

23

關於緩存,幾個次要的點:

它使用斜線對象類型和id的分離是值得,這是軌道公約。更好的是,ActiveRecord模型提供了cacke_key實例方法,它將提供表名和id「cities/13」等的唯一標識符。

對after_save過濾器的一個小修改。由於您手邊有數據,因此您不妨將其寫回緩存,而不是將其刪除。這是節省您的行程單到數據庫;)

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

至於問題的根源,如果你一直拉@ user.city.name,有兩個真正的選擇:

  • 將用戶的城市名稱非規範化到用戶行。 @ user.city_name(保留city_id外鍵)。這個值應該在保存時寫入。

- 或 -

  • 實現你User.fetch方法渴望加載城市。只有在城市行的內容不會改變的情況下才能這樣做(例如,名稱等),否則您可能會在緩存失效方面打開一堆蠕蟲。

個人意見: 實現基於獲取方法基本ID(或使用插件)與memcached的集成和非規範化的城市名稱到用戶的行。

我個人並不是一個緩存模型樣式插件的狂熱粉絲,我從來沒有見過這樣一個節省了大量開發時間的工作,而這些工作並沒有匆匆發展。

如果您遇到過多的數據庫查詢,如果您尚未加載(通過:include),則絕對值得檢查。這應該是減少數據庫查詢數量的第一步。

0

如果您需要加快對時間變化不大的數據的sql查詢,那麼您可以使用物化視圖。

matview將查詢結果存儲到其自己的表格式結構 中,從中可以查詢數據。不可能添加 或刪除行,但其餘時間的行爲就像 實際表一樣。查詢速度更快,並且matview本身可以被索引爲 。

在編寫本文時,Matviews在Oracle DB,PostgreSQL,Sybase,IBM DB2和Microsoft SQL Server中本地可用。不幸的是,MySQL 沒有提供對matview的原生支持,但 是它的開源替代品。

這裏是如何在Rails的

使用matviews

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

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