我已经在一个运行很多次的查询上设置了缓存..查询本身并不是那么慢,但每次请求都会运行多次,因此有点缓存可能有所帮助.我已经启用了缓存,但似乎没有什么区别......如何判断我的查询是否被缓存?
我正在设置缓存: q.setCachedWithin("#createTimespan(0, 1, 0, 0)#");
这是我的完整查询准备:
q = New Query();
q.setSQL("SELECT * FROM guest_booking WHERE room_id = :roomID and check_in <= :iDate and check_out > :iDate and status != 0");
q.setName("checkAvailability");
q.setCachedWithin("#createTimespan(0, 1, 0, 0)#");
q.addParam(name="iDate", value="#createODBCDate(arguments.date)#", cfsqltype="cf_sql_date");
q.addParam(name="roomID", value="#createODBCDate(arguments.room_id)#", cfsqltype="cf_sql_integer");
qResult = q.execute().getresult();
Run Code Online (Sandbox Code Playgroud)
调试输出显示:
checkAvailability (Datasource=accom_crm, Time=16ms, Records=1) in C:\ColdFusion9\CustomTags\com\adobe\coldfusion\base.cfc @ 16:15:56.056
SELECT * FROM guest_booking WHERE room_id =
?
and check_in <=
?
and check_out >
?
and status != 0
Query Parameter Value(s) -
Parameter #1(cf_sql_integer) = 56
Parameter #2(cf_sql_date) = {ts '2011-11-14 00:00:00'}
Parameter #3(cf_sql_date) = {ts '2011-11-14 00:00:00'}
Run Code Online (Sandbox Code Playgroud)
提前谢谢了..
贾森
在SHAWN的回答之后编辑
更改了以下两行查询预处理:查询名称现在因不同的查询而不同...从传入的参数动态创建
q.setName("check#arguments.room_id##DateFormat(arguments.date,'ddmmyy')#");
Run Code Online (Sandbox Code Playgroud)
createTimeSpan从引号中删除,因此不作为字符串传入.
q.setCachedWithin(createTimespan(0, 1, 0, 0));
Run Code Online (Sandbox Code Playgroud)
我也尝试通过一个毫无准备的查询发送(不使用addparam(),但只是在查询字符串中直接渲染变量),但没有区别.
编辑2在SHOWN之后的第三个EDITANWSER下面 Shawn ..在编辑3上很好的拾取!!! 你已经孤立问题所在.(任何读这篇文章,快速,向上投票的肖恩的答案,他在干草堆中发现了一根针)
将日期作为参数传递不会缓存.例如.
q.setSQL("SELECT booking_id FROM guest_booking WHERE room_id = :roomID and check_in <= :iDate and check_out > :iDate and status != 0");
q.addParam(name="iDate", value="#createODBCDate(arguments.date)#", cfsqltype="cf_sql_date");
Run Code Online (Sandbox Code Playgroud)
只是将其作为变量传递不会缓存..例如.
q.setSQL("SELECT booking_id FROM guest_booking WHERE room_id = :roomID and check_in <= #createODBCDate(arguments.date)# and check_out > #createODBCDate(arguments.date)# and status != 0");
Run Code Online (Sandbox Code Playgroud)
但硬编码日期是否缓存..例如.
q.setSQL("SELECT booking_id FROM guest_booking WHERE room_id = :roomID and check_in <= {ts '2011-12-16 00:00:00'} and check_out > {ts '2011-12-16 00:00:00'} and status != 0");
Run Code Online (Sandbox Code Playgroud)
这一切都很好,但很明显我不能对日期进行硬编码......显然每天的日期都会发生变化,但即使我运行同一个查询并且动态传递相同的日期(查询语法完全相同) ),如果日期作为变量传递,查询将不会缓存..只有当它们被硬编码到查询中时... wierd ..将继续播放并查看我能找到的内容.
谢谢Shawn查明问题!!!
如果它被正确缓存,您的调试输出将包含一小部分附加信息,调整为:
checkAvailability (Datasource=accom_crm, Time=0ms, Records=1, Cached Query)
Run Code Online (Sandbox Code Playgroud)
有些东西阻止了您的查询被缓存.
我注意到你对.setCachedWithin()的调用有一个字符串被传递给它 - 或者更确切地说,你通过用引号限定它并使用#符号来使它成为一个字符串.
尝试传递从CreateTimeSpan()返回的实际值,而不将其转换为字符串,如下所示:
q.setCachedWithin(createTimeSpan(0, 1, 0, 0));
Run Code Online (Sandbox Code Playgroud)
- 编辑 -
关于查询缓存的一些其他花絮:
从调用到调用,所有这些属性必须保持不变,以便ColdFusion将其视为可缓存的查询.你在上面提到你尝试过调用addParam(),但仍然没有运气......
...尝试使用静态查询名称,而不是使用变量名称 - 请参阅是否进一步了解
q.setName("checkTestQuery");
Run Code Online (Sandbox Code Playgroud)
- 第二次编辑 -
另一个经常被忽视的问题是ColdFusion服务器的时钟.确保正确设置了CFServer的日期/时间.这可能听起来很愚蠢,但我见过许多"生产"服务器,其时钟完全关闭,并没有设置到正确的时区,更不用说时间了......当然,时间在内容中具有重要意义.缓存.
- 第3次编辑 -
在重新阅读并查看所有内容后,我建议您再看一下我上面提到的关于SQL语句需要相同的第二点,并且您的WHERE子句依赖于受日期影响的变量/ time,隐含地可以在每个请求上更改.
...并且,由于SQL语句必须保持相同才能被缓存,因此CF会丢弃任何缓存它的尝试.
尝试暂时重构SQL语句,而不使用WHERE子句查找这些日期变量...并查看它产生的内容.