Beginners Guide to Memory Based Caching

In my opinion, one of the coolest "advanced" concepts of ColdFusion is memory based query caching. Sure, caching may not make it into the Cool Things to Do In ColdFusion Hall of Fame, but it is close to the top of my list for the simple fact that caching is a quick and easy way to drastically improve performance. In this post I'd like to talk about memory based query caching to store data returned from a stored procedure. Obviously this method has certain limitations and should only be used when and where approriate (for example, you certainly would not cache resultsets where there is a need for 'live' data). Since caching and performance are always hot topics in the ColdFusion community, I welcome any and all feedback/suggested alternatives/warnings in the comments (just keep it friendly).

Assumptions:

You have been requested to create a new report. The report is based on a stored procedure which has already been created for you. The stored proc returns three resultsets, each with summary data that need to be displayed to the user. The proc runs in just over 2500ms. The data is not required to be 'live' - day old data is 'ok'.

Step 1 - Set Up A Container For The Query

First I set up a struct in my application.cfc file to house the cached queries.

application.cfc

<!--- other stuff... --->
<cffunction name="onApplicationStart">
   <!--- instatiate the cfc --->
   <cfset application.theCFC = createObject("component", "path.to.theComponent")>
   <cfset application.cachedQueries = structNew()>
   <cfset application.cachedQueries.resultOne = queryNew("")>
   <cfset application.cachedQueries.resultTwo = queryNew("")>
   <cfset application.cachedQueries.resultThree = queryNew("")>
</cffunction>
<!--- other stuff... --->

Step 2 - Creating the Query

The second step I would take is to create a method within a cfc to retrieve the data (or create a new cfc if absolutely necessary). The method is a simple one:

theComponent.cfc

<cffunction name="getTheDataToCache" output="false" hint="gets the data to be cached" access="remote" returntype="struct">
   <cfset var returnStruct = structNew()>
   <cfset var resultOne = queryNew("")>
   <cfset var resultTwo = queryNew("")>
   <cfset var resultThree = queryNew("")>

   <cfstoredproc datasource="#variables.dsn#" procedure="storedProcName">
      <cfprocresult name="resultOne" resultset="1" />
      <cfprocresult name="resultTwo" resultset="2" />
      <cfprocresult name="resultThree" resultset="3" />
   </cfstoredproc>
   
   <cfset returnStruct.resultOne = resultOne>
   <cfset returnStruct.resultTwo = resultTwo>
   <cfset returnStruct.resultThree = resultThree>
      
   <cfreturn returnStruct/>
</cffunction>

Step 3 - Caching the Query

There are a few alternatives at this point. Assuming the performance of the query is not absolutely horrible, I could have simply invoked the getTheDataToCache method in the onApplicationStart method of the application.cfc and been done. From there it would simply be a case of outputting the application variable (or querying it with QofQ if needed). Lets assume though that the proc isn't the quickest. In that case, I'd rather not run this onApplicationStart. Instead, I like to create a separate template which invokes the component and caches it. I then schedule the execution of this template during off hours.

<!--- invoke the getTheDataToCache method --->
<cfset theDataStruct = application.theCFC.getTheDataToCache()>

<!--- first lock the scope --->
<cflock scope="application" timeout="30">
   <!--- store each recodset in the application.cachedQueries struct --->
   <cfset application.cachedQueries.resultOne = theDataStruct.resultOne>
   <cfset application.cachedQueries.resultTwo = theDataStruct.resultTwo>
   <cfset application.cachedQueries.resultThree = theDataStruct.resultThree>
</cflock>

Step 4 - Accessing/Outputting The Query

From here, the query can be accessed just like any other query - the tricky thing for a beginner is the fact that the query at this point is buried pretty deep in the application scope.

<!--- dump the query --->
<cfdump var="#application.cachedQueries.resultOne#">

<!--- query the query --->
<cfquery name="yetAnotherStinkingQuery" dbtype="query">
select stuff
from application.cachedQueries.resultOne
where stuff = 'other stuff'
</cfquery>

It may look funny to access a query column as application.cachedQueries.resultOne.columnName but it's really the same as theQuery.columnName. You could also always set "theQuery" equal to the cached query so that it could be directly referenced without the extended dot notation, for example:

<cfset theQuery = application.cachedQueries.resultOne>

<cfoutput>
#theQuery.columnName#
</cfoutput>

So that's my technique for memory based query caching. As I said above, be careful when and where you use this technique.

Again, any suggestions/alternatives are welcomed!

Comments
Todd,
The code on the page is unreadable, is that normal?? I've never noticed it before. I'm using FF.

Thanks for reminding me about caching, I totally forgot about it. This method will also be useful for sites that using a database to lay out the navigation bar.

Ryan
# Posted By Ryan Everhart | 10/2/06 8:31 PM
Send me a screenshot? Everything looks fine on my end (in FF)...

todd (at) cfsilence (dot) com

haven't set up the gmail yet!
# Posted By todd | 10/2/06 8:36 PM

Calendar

Sun Mon Tue Wed Thu Fri Sat
  12345
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31   

Subscribe

Enter your email address to subscribe to this blog.

Tags

actionscript ajax blogging cfsnippets coldfusion flash forms flex misc model-glue off topic personal project learn slidesix sql

Recent Comments

More CF+Java: Compiling Classes And Persisting Objects
Getburl said: I have been attempting to get Db4o working in my CF application and I have not succeeded. I would lo... [More]

Thoughts On Ajax Frameworks And ColdFusion/Adobe
Erast said: http://fanniecollins.10gb... emo http://gracetrevino.phree...... [More]

Extending Ext With Ext Extensions
Erast said: http://fanniecollins.10gb... emo http://gracetrevino.phree...... [More]

CF Needs An Open Source Contact List Importer
Kay Smoljak said: Heh, the fact that sites DO it doesn't mean they SHOULD. To us it's ok, but to a non-tech-savvy user... [More]

A Few Project Updates
Helena said: Now punctually what is the situation ? [More]

RSS


coldfusionbloggers

FullAsAGoog MXNA

Consumed By Feed-Squirrel.com