如何判断coldfusion查询是否缓存?

Jas*_*son 3 coldfusion

我已经在一个运行很多次的查询上设置了缓存..查询本身并不是那么慢,但每次请求都会运行多次,因此有点缓存可能有所帮助.我已经启用了缓存,但似乎没有什么区别......如何判断我的查询是否被缓存?

我正在设置缓存: 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查明问题!!!

Sha*_*mes 9

如果它被正确缓存,您的调试输出将包含一小部分附加信息,调整为:

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)

- 编辑 -

关于查询缓存的一些其他花絮:

  1. 查询的名称必须相同.
  2. SQL语句(在其所有参数化形式中)必须相同.
  3. 数据源必须相同.
  4. 如果使用,用户名和密码必须相同.
  5. DBTYPE必须相同.

从调用到调用,所有这些属性必须保持不变,以便ColdFusion将其视为可缓存的查询.你在上面提到你尝试过调用addParam(),但仍然没有运气......

...尝试使用静态查询名称,而不是使用变量名称 - 请参阅是否进一步了解

q.setName("checkTestQuery");
Run Code Online (Sandbox Code Playgroud)

- 第二次编辑 -

另一个经常被忽视的问题是ColdFusion服务器的时钟.确保正确设置了CFServer的日期/时间.这可能听起来很愚蠢,但我见过许多"生产"服务器,其时钟完全关闭,并没有设置到正确的时区,更不用说时间了......当然,时间在内容中具有重要意义.缓存.

- 第3次编辑 -

在重新阅读并查看所有内容后,我建议您再看一下我上面提到的关于SQL语句需要相同的第二点,并且您的WHERE子句依赖于受日期影响的变量/ time,隐含地可以在每个请求上更改.

...并且,由于SQL语句必须保持相同才能被缓存,因此CF会丢弃任何缓存它的尝试.

尝试暂时重构SQL语句,而不使用WHERE子句查找这些日期变量...并查看它产生的内容.