我已经在很多次运行的查询上设置了缓存..查询本身并不是那么慢,但是每次请求都会运行多次,因此有点缓存可能会有所帮助。我已经启用了缓存,但似乎没有什么区别......如何判断我的查询是否被缓存?
我正在设置缓存: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();
调试输出显示:
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'}
非常感谢...
杰森
编辑后显示
更改了以下两行查询预处理: 对于不同的查询,查询名称现在是不同的..从
中传递的参数动态创建q.setName("check#arguments.room_id##DateFormat(arguments.date,'ddmmyy')#");
createTimeSpan从引号中删除,因此不以字符串形式传入。
q.setCachedWithin(createTimespan(0, 1, 0, 0));
我也试过通过一个没有准备的查询发送(不使用addparam(),只是在查询字符串中直接渲染变量),但没有区别......
编辑2在SHAWN的第三个EDITANWSER之后编辑 Shawn ..在编辑3上很好的拾取!!!你已经孤立问题所在。 (任何读这篇文章的人,快速,向上投票Shawn的答案,他在干草堆中发现了一根针)
将日期作为参数传递不会缓存..例如..
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");
将其作为变量传递不会缓存..例如..
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");
但是对日期进行硬编码才能缓存..例如..
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");
这一切都很好,但很明显我不能对日期进行硬编码......显然每天的日期都会发生变化,但即使我运行同一个查询并且动态传递相同的日期(查询语法为完全一样),如果日期作为变量传递,查询将不会缓存..只有当它们被硬编码到查询中时... wierd ..将继续播放并查看我能找到的内容。
谢谢Shawn查明问题!!!
答案 0 :(得分:9)
如果它被正确缓存,您的调试输出将只包含一小部分附加信息:
checkAvailability (Datasource=accom_crm, Time=0ms, Records=1, Cached Query)
阻止查询被缓存。
我注意到你对.setCachedWithin()的调用有一个字符串被传递给它 - 或者说,你通过用引号限定它并使用#符号来使它成为一个字符串。
尝试传递从CreateTimeSpan()返回的实际值,而不将其转换为字符串,如下所示:
q.setCachedWithin(createTimeSpan(0, 1, 0, 0));
- 编辑 -
关于查询缓存的一些其他花絮:
所有这些属性必须在调用之间保持不变,以便ColdFusion将其视为可缓存的查询。你在上面提到你尝试过调用addParam(),但仍然没有运气......
...尝试使用静态查询名称,而不是使用变量名称 - 请参阅是否有进一步的
q.setName("checkTestQuery");
- 第二次编辑 -
另一个经常被忽视的问题是ColdFusion服务器的时钟。确保正确设置了CFServer的日期/时间。这可能听起来很愚蠢,但我看到很多“生产”服务器的时钟完全关闭,并没有设置到正确的时区,更不用说时间......当然,时间在内容中具有重要意义。缓存。
- 第3次编辑 -
在重新阅读并查看所有内容之后,我建议你再看一下我上面提到的关于SQL语句需要相同的第二点,并且你的WHERE子句依赖于受日期/时间影响的变量,每个请求都可以隐式更改。
...并且,由于SQL语句必须保持相同才能被缓存,因此CF会丢弃任何缓存它的尝试。
尝试暂时重构SQL语句,而不使用WHERE子句查找这些日期变量......并查看它产生的内容。
答案 1 :(得分:1)
Shawn的建议大多是好的,但检查查询是否被缓存的最简单方法是更新基础数据,看看requerying是否为您提供以前缓存的(一切顺利)数据,或反映更新。如果它反映了更新,那么它不会被缓存......
请注意,您不需要使用查询名称(根据您的更新)。当参数不同时,CF将自行计算,并缓存单独的结果集。