views:

289

answers:

5

We are developing an ASP.NET HR Application that will make thousands of calls per user session to relatively static database tables (e.g. tax rates). The user cannot change this information, and changes made at the corporate office will happen ~once per day at most (and do not need to be immediately refreshed in the application).

About 2/3 of all database calls are to these static tables, so I am considering just moving them into a set of static objects that are loaded during application initialization and then refreshed every 24 hours (if the app has not restarted during that time). Total in-memory size would be about 5MB.

Am I making a mistake? What are the pitfalls to this approach?

+1  A: 

Think: Premature Optimization. You'll still need to deal with the data as tables eventually anyway, and you'd be leaving an "unusual design pattern".

With event default caching, a dbms is plenty efficient with static data anyway, especially only 5M of it. And the dbms partitioning you're describing is often described as an antipattern. One example: multiple identical databases for multiple clients. There are other questions here on SO about this pattern. I understand there are security issues, but doing it this way creates other security issues. I've recently seen this same concept in a medical billing database (even more highly sensitive) that ultimately had to be refactored into a single database.

If you do this, then I suggest you at least wait until you know it's solving a real problem, and then test to measure how much difference it makes. There are lots of opportunities here for Unintended Consequences.

le dorfier
+2  A: 

From the info you present, it looks like you definitely should cache this data -- rarely changing and so often accessed. "Static" objects may be inappropriate, though: why not just access the DB whenever the cached data is, say, more than N hours old?

You can vary N at will, even if you don't need special freshness -- even hitting the DB 4 times or so per day will be much better than "thousands [of times] per user session"!

Best may be to keep with the DB info a timestamp or datetime remembering when it was last updated. This way, the check for "is my cache still fresh" is typically very light weight, just get that "latest update" info and check it with the latest update on which you rebuilt the local cache. Kind of like an HTTP "if modified since" caching strategy, except you'd be implementing most of it DB-client-side;-).

Alex Martelli
That's what databases do anyway, all by themselves.
le dorfier
Some do, some don't, some vary by the phase of the moon (or, the DB's cache can get under pressure from other clients, etc), plus, if the DB server is remote from the web server, the data transfer implies latency anyway. A local cache is more under your control.
Alex Martelli
Do you mean use the ASP.NET Cache object instead of a set of static objects (i.e. in a singleton)? We've actually never used it for data object caching, and figured there were drawbacks.
Jess
le dorfier - we're using an ORM, so we'd just pull the data into arrays of objects with the same relationships. The code already handles related tables, so no joins necessary.
Jess
Doesn't the ORM have objects that comprise data from both static and dynamic data, joined?
le dorfier
@le dorfier - no, we have multiple databases - one per client containing dynamic data and one (for all clients) containing static data. No joining between the two databases. Also, as of now the databases are on a separate database server - many thousands of extra calls across the network per minute seems excessive if there's an easy way to cache the data locally, right? Even if SQL Server caches the data, the network is going to slow things down. It also doesn't seem to make sense to put SQL Server on the web servers just to support this static data.
Jess
Then have you considered replicating such a small dataset to the servers? Especially since you're giving up such a (to me) clearly useful opportunity to JOIN as needed? Not saying for sure (because I don't know enough) but this sounds like there are other prematurely optimized design patterns here, and you're complicating the design to compensate. How much actual testing of alternatives are you doing?
le dorfier
+2  A: 

If you decide to cache the data (vs. make a database call each time), use the ASP.NET Cache instead of statics. The ASP.NET Cache provides functionality for expiry, handles multiple concurrent requests, it can even invalidate the cache automatically using the query notification features of SQL 2005+.

If you use statics, you'll probably end up implementing those things anyway.

There are no drawbacks to using the ASP.NET Cache for this. In fact, it's designed for caching data too (see the SqlCacheDependency class http://msdn.microsoft.com/en-us/library/system.web.caching.sqlcachedependency.aspx).

Brannon
+1  A: 

With caching, a dbms is plenty efficient with static data anyway, especially only 5M of it.

True, but the point here is to avoid the database roundtrip at all.

ASP.NET Cache is the right tool for this job.

Ariel
I understand that's the point. But most applications of this pattern imply (to me anyway) decomposing joins in SQL (especially using an ORM) into list references, which is usually false economy. As @Mathias points out. I don't see a single discussion here about measuring and comparing design alternatives.
le dorfier
+1  A: 

You didnt state how you will be able to find the matching data for a user. If it is as simple as finding a foreign key in the cached set then you dont have to worry. If you implement some kind of filtering/sorting/paging or worst searching then you might at some point miss the quereing capabilities of SQL.

ORM often have their own quereing and linq makes things easy to, but it is still not SQL. (try to group by 2 columns)

Sometimes it is a good way to have the db return the keys of a resultset only and use the Cache to fill the complete set.

Malcolm Frexner