Efficiently store/retrieve global settings for Rails app in DB
I have a number of global application settings which are stored in a table called "settings" in the DB. It has three columns: id, key, value.
Now let's say I have a product listing which lists, say, 30 products. Displaying each of these products requires retrieving a certain setting "exchange rate" from the settings table. The way I've done it is I added a function "exchange_rate" to the application helper which looks for the settings row with key "exchange rate" and retrieves the value.
What's wrong now you may ask? Well, nothing really, it works just fine, but when I follow the development server log I notice each request has 30 of these entries:
CACHE (0.0ms) SELECT settings
.* FROM settings
WHERE (settings
.key
= 'exchange_rate') LIMIT 1
CACHE (0.0ms) SELECT settings
.* FROM settings
WHERE (settings
.key
= 'exchange_rate') LIMIT 1
It looks really ugly and clutters my log. The reason is obvious: The DB entry is retrieved 30 times. It doesn't appear to have any DB load because it says CACHE, so there shouldn't be any performance problem (or is there?? I don't know).
My question is: Would it be "cleaner" and more reasonable to retrieve this global variable (exchange rate) ONCE and then save it som开发者_运维技巧ewhere (where?) so that I don't get these seemingly redundant (although cached) DB requests?
Yes, the best way to get around this would be to store the value in a class variable. For example:
class Settings
def self.exchange_rate
@@exchange_rage ||= (execute your SQL query and get the result here)
end
end
That way anytime you call Settings.exchange_rate you will only perform the query the first time. The rest of the times the @@exchange_rate class variable will be used.
In your original example, the only performance impact is the generation of the SQL query and the hitting of the cache, so it definitely exists, but is not as bad as actually hitting the database every time you want the exchange rate.
精彩评论