【发布时间】:2016-02-12 17:28:35
【问题描述】:
我从我们的大型机数据库中提取了一个日历表并保存为本地 Access 表。该表的历史可以追溯到 1930 年代(我知道我们至少在一个地方使用了 50 年代),产生了 31k 条记录。此日历表有 3 个感兴趣的字段:
Bus_Dt - 每天,而不仅仅是工作日。主键
Bus_Day_Ind - 指示当天是否是股票市场的有效工作日。
Pir_Bus_Dt - 前一个工作日。包含一些错误(大约 50 个),都是旧的。
我编写了一个查询来检索当前日历日或之后的第一个工作日,但它运行得非常慢。 (5 分钟以上)我检查了 showplan 输出,发现它是通过 x-join 运行的,它在 30k+ 记录表之间提供了大约 1000 万的解决方案空间(和日期比较)。不过,实际的任务并不难,只需简单的排序,Excel 就能在最短的时间内轻松完成。
因此,我的问题是,有没有办法解决查询性能不佳的问题,或者这是 SQL 的固有故障? (DB2 在大型机上运行也很慢,虽然不是很慢。在问题上抛出循环等等。)其次,如果我要信任 prir_bus_dt,我能做得更好吗?或者限制日期范围(又名“作弊”),或者我还没有想到的任何其他技巧?
SQL:
SELECT TE2Clndr.BUS_DT AS Cal_Dt
, Min(TE2Clndr_1.BUS_DT) AS Next_Bus_Dt
FROM TE2Clndr
, TE2Clndr AS TE2Clndr_1
WHERE TE2Clndr_1.BUS_DAY_IND="Y" AND
TE2Clndr.BUS_DT<=[te2clndr_1].[bus_dt]
GROUP BY TE2Clndr.BUS_DT;
展示计划:
Inputs to Query
Table 'TE2Clndr'
Table 'TE2Clndr'
End inputs to Query
01) Restrict rows of table TE2Clndr
by scanning
testing expression "TE2Clndr_1.BUS_DAY_IND="Y""
store result in temporary table
02) Inner Join table 'TE2Clndr' to result of '01)'
using X-Prod join
then test expression "TE2Clndr.BUS_DT<=[te2clndr_1].[bus_dt]"
03) Group result of '02)'
同样,问题是,这是否可以做得更好(更快),还是已经做到最好了?
【问题讨论】:
-
由于您已将表导入 Access 并且该表不太可能经常刷新,您可以简单地添加一个 NEXT_BUS_DT 列,使用任何必要的方式填充它(即使它不是特别有效),然后直接查询“下一个营业日期”值。这也将有助于避免以后出现“查询必须使用可更新记录集”的问题。
-
这是我在下面的“作弊”成功之前修复速度的默认计划。我尽量避免“制作表格”类型的执行,因为每个步骤都是一个可能被遗忘的项目——尤其是当它是一个每年只使用一次的步骤时。我也关心这个问题背后的“理论”,因为我有时在 DB2 服务器上使用相同的逻辑,而我没有表能力。 DB2 获得了正确的基本查询,但有时当它是较大任务中的子查询并因此产生糟糕的查询计划时会感到困惑。 (看不到来自 DB2 的计划,也被禁用了。)