2

我们有一个分析图表,它首先查询数据库日志表以从优化查询中提取所有相关信息,只选择需要的内容以及获取相关的开始和结束 ID,因为该表有数百万条记录。提取初始查询后,我们使用 ColdFusion 的查询查询来处理该数据以显示不同的图表。

您可以看到此示例中的实际外部数据库调用在 31 毫秒内抓取了 2,240 条记录:

qryGetLogs (Datasource=ourDSN, Time=31ms, Records=2204) 

我们有一个图表,它显示一周中每一天的每小时视图,然后构建一个 jQuery 图表来显示它们。从最初的设计来看,这些查询的执行时间几乎可以忽略不计,通常为 0 毫秒。因为我们每周 7 天在一天 (24) 中的每个小时循环,即 168 次查询 - 这是不多次调用外部数据库的主要原因之一。

现在看来,这些查询中的许多(但不是全部)查询的运行时间是初始数据库调用的 100 倍以上。他们中的大多数都使用 BETWEEN 日期范围函数来选择每一天和每一小时部分的记录:

qryViewsPerHour (Datasource=, Time=4312ms, Records=5)
SELECT createdOn, DayOfWeek
FROM qryGetLogs
WHERE  (CreatedOn BETWEEN '2012-09-03 0:00:00' AND '2012-09-03 0:59:59')
AND (DayOfWeek = 2)

您可以看到另一个查询的查询花费了 4,312 毫秒,并且正在搜索具有 2,240 条记录的查询。以下是许多后续查询的查询时间:

qryViewsPerHour (Datasource=, Time=4610ms, Records=5)
qryViewsPerHour (Datasource=, Time=4187ms, Records=8)
qryViewsPerHour (Datasource=, Time=5062ms, Records=6)
qryViewsPerHour (Datasource=, Time=3985ms, Records=0)
qryViewsPerHour (Datasource=, Time=4828ms, Records=2)
qryViewsPerHour (Datasource=, Time=5750ms, Records=0)
qryViewsPerHour (Datasource=, Time=3016ms, Records=4)
qryViewsPerHour (Datasource=, Time=3625ms, Records=6)
qryViewsPerHour (Datasource=, Time=6265ms, Records=11)

所以你可以通过这些查询看到,它增加了 40 秒的加载时间!但请注意,下一个查询只有 78 毫秒,记录比之前的任何一个查询都多,而且在此之后,时间会更好:

qryViewsPerHour (Datasource=, Time=78ms, Records=18)
qryViewsPerHour (Datasource=, Time=62ms, Records=7)
qryViewsPerHour (Datasource=, Time=63ms, Records=12)
qryViewsPerHour (Datasource=, Time=78ms, Records=34)
qryViewsPerHour (Datasource=, Time=78ms, Records=9)

那些美好的时光会持续一段时间,然后BAM!回到 2-6 秒的查询。

qryViewsPerHour (Datasource=, Time=4891ms, Records=13)
qryViewsPerHour (Datasource=, Time=1984ms, Records=8)
qryViewsPerHour (Datasource=, Time=4875ms, Records=4)
qryViewsPerHour (Datasource=, Time=6203ms, Records=0)

总而言之,加载需要几秒钟,加载需要 100-400 秒,这只是每周报告!我们还将它用于月度报告。

我已经监控了服务器,并确保我是唯一运行请求的人或进程,所以不应该是 CPU 的资源被其他东西吃掉了,我还监控了 CPU 请求,它是稳定的由 JRUN.exe 使用。

有人对这个问题有什么建议吗?它快把我逼疯了!

谢谢你的帮助。

4

4 回答 4

12

通常,查询的查询速度非常快。但是,有时当交易量增加时可能需要更长的时间。由于您在 ColdFusion 文档推荐的 5,000 到 50,000 行推荐范围内,它只能是一回事。有些地方正在翻译一些数据以获得结果。在这种情况下,它是您指定的日期时间。时间值有一个前导零。我知道这听起来很奇怪。

更改: 在哪里(在 '2012-09-03 0:00:00' 和 '2012-09-03 0:59:59' 之间创建)

TO: WHERE(在 '2012-09-03 00:00:00' 和 '2012-09-03 00:59:59' 之间创建)

我对此进行了测试,发现结果更好。

于 2012-09-06T14:20:38.033 回答
3

虽然根据我的经验,Coldfusion 具有执行查询查询的功能,但它是最后的手段。原因是它是多么低效和有限。CF 是一种编程语言,而不是 SQL 语言,因此它没有任何真正的 DB 所具有的优化功能。

我强烈建议将查询推送到数据库中,如果您有一个支持视图的数据库,我还建议您根据原始查询创建一个视图,这样您只需对视图执行子查询,而不是整个原始表。

尽可能避免查询查询,尤其是在处理大型数据集时,因为它必须作为庞大的 Java 对象全部存储在内存中。正如 Russ 指出的那样,它会受到垃圾收集器的影响,并且随着您的报告的增长,可能会导致内存不足的问题。(我曾经用过大的环比打翻了我的电脑)

于 2012-09-06T11:31:19.157 回答
2

在我看来,您正在看到 JVM 垃圾收集器在工作。一种选择是尝试运行 JVM 监控工具,以帮助调整 JVM 以满足您的特定需求。另一种选择是在数据库上运行子查询,而不是查询查询。

于 2012-09-05T22:56:26.703 回答
1

我很高兴你发布了,因为我一直认为这比往返服务器要好。

但是如何使用:

cachedWithin="#CreateTimeSpan(0,0,1,0)#"

这可能与查询的查询一样好。

于 2012-09-06T15:39:18.183 回答