Data Caching Using Text Files in ASP
Written by Nick Dunn published 19th Mar 2006 | Comment on this article
If your web application regularly performs complex database queries, you might be able to improve performance by caching the results.
Introduction
There are numerous ways of speeding up your web applications, and improving data access efficiency is one of them. A method of increasing data access efficiency is to cache frequently accessed data. This would be a list of forum posts, populating a drop down menu with country names, or performing complex cross-table queries in large databases. There are three main ways of caching data. In this article I document the third method.
a) Caching within the database.
More advanced database servers such as MySQL and SQL Server (not Access) support indexing. Frequenty run queries are effectively cached within the database itself. However this isn't always easy to implement.
b) Caching in the web server memory.
Data can be stored in the web server session or application memory state. This is great for small, temporary pieces of data such as a username login session, but for larger datasets you may be putting the shared web server under strain.
c) Cache to a file.
Once your data is selected, you save its contents, including HTML formatting, to a text file. This can simply be written back to the browser at runtime, bypassing the database query completely.
The concept
Firstly we need to decide what type of file we are going to store our cached data in. In an ideal world we would use XML, or some type of CSV database, just storing the raw data. However this data would still require iterations and HTML formatting. My own method is to query the database once, format into HTML once, save it as a text file, and write it back to the browser when required. To do so we need three functions: to read our cached file, to check if our cached version has expired, and to create a new refreshed cached file.
The first function is used to check whether our cached data has expired or not. It would be rare to never want your cache to be updated, so this function accepts parameters to allow you to decide how often the cache should be updated (a value and a time unit). The first parameter is the name of the cache file you are checking, for example "latestPosts.txt". The other two parameters determine the cache expiry time, for example "2" and "hours".
Function cacheFileIsExpired(strFileName, cacheInterval, cacheIntervalUnit)
If cacheInterval = 0 Then
cacheFileIsExpired = True
Exit Function
End IfOn Error Resume Next
Dim cacheFSO : Set cacheFSO = CreateObject("Scripting.FileSystemObject")
Dim cacheFile : Set cacheFile = cacheFSO.GetFile("d:\webs\mydomain.com\cache\" & strFileName)
Dim strDate : strDate = cacheFile.DateLastModified
Set objFile = NothingSelect Case cacheIntervalUnit
Case "minutes" : strUnit = "n"
Case "hours" : strUnit = "h"
Case "days" : strUnit = "d"
End SelectcacheFileIsExpired = (DateDiff(strUnit,CDate(strDate), Now()) > cacheInterval)
If err.Number <> 0 Then
cacheFileIsExpired = True
End IfSet cacheFile = Nothing
Set cacheFSO = Nothing
End Function
If the cached file has expired, or doesn't exist, the function returns True. If so, we need to refresh our cache.
The following function accepts two parameters. The first is the cache file we are updating ("latestPosts.txt"), and the second is the complete contents of the cache. For example, if we want to cache a list of the ten latest forum posts, we would query the database, loop through records, format with HTML and add the contents to strText. The function itself merely creates a new text file.
Function writeCachedFile(strFileName, strText)
Dim cacheFSO : Set cacheFSO = CreateObject("Scripting.FileSystemObject")
Dim cacheFile : Set cacheFile = cacheFSO.CreateTextFile("d:\webs\mydomain.com\cache\" & strFileName, True, True)
cacheFile.Write(strText)
cacheFile.Close
Set cacheFile = Nothing
Set cacheFSO = Nothing
writeCachedFile = strText
End Function
The final function is similar to the one above. However instead of creating a new text file, we pass the function the name of the cache file we want to retrieve, and it returns its contents.
Function getCachedFile(strFileName)
Dim cacheFSO : Set cacheFSO = CreateObject("Scripting.FileSystemObject")
Dim cacheFile : Set cacheFile = cacheFSO.OpenTextFile("d:\webs\mydomain.com\cache\" & strFileName,1,False,-1)
getCachedFile = cacheFile.ReadAll
Set cacheFile = Nothing
Set cacheFSO = Nothing
End Function
Putting it all together
Let's run through an example of how to use these functions together. Keeping with the example above of compiling a list of the top 10 forum posts, let's cache the results. This example assumes you have saved the above three functions into a new ASP file named "caching.asp", which we will call as an include file in the following example.
<!--#include file="caching.asp"-->
<%If cacheFileIsExpired("latestPosts.txt", 2, "hours") Then
Dim objConn : Set objConn = Server.CreateObject("ADODB.Connection")
With objConn
.Provider = "Microsoft.Jet.OLEDB.4.0"
.Open "d:\webs\mydomain.com\db\forum.mdb"
End WithDim objPosts : Set objPosts = Server.CreateObject("ADODB.Recordset")
objPosts.Open "Select Top 10 * From tblPosts", 0, 1, objConnDo Until objPosts.EOF
strPosts = strPosts & "<li>" & objPosts("PostTitle") & "</li>"
objPosts.MoveNext
LoopstrPosts = "<ul>" & strPosts & "</ul>"
objPosts.Close
Set objPosts = Nothing
objConn.Close
Set objConn = NothingResponse.Write(writeCachedFile("latestPosts.txt", strPosts))
Else
Response.Write(getCachedFile("latestPosts.txt"))
End If
%>
The first function call checks whether the cache is more than 2 hours old. If not, we don't touch the database at all, and simply write the contents of the cache text file. If the cache needs updating, we query the database and create the new cached file.
This is a relatively simple concept, and I hope these functions make it easier for you to start caching your data right away! I've found that it massively increases page speeds often by a matter of several full seconds (for particularly data-heavy applications). Give it a go :-)