首先,一些背景。
我们有一个订单处理系统,员工在应用程序中输入有关订单的计费数据,该应用程序将其存储在 sql server 2000 数据库中。这个数据库不是真正的计费系统:它只是一个保存位置,以便记录可以通过夜间批处理运行到大型机系统中。
此批处理是由外部供应商提供的罐装第三方包装。它应该做的部分工作是为任何被拒绝的记录提供报告。拒绝报告是手动处理的。
不幸的是,事实证明第三方软件并没有捕捉到所有的错误。我们有单独的进程将数据从大型机拉回数据库中的另一个表,并将拒绝的费用加载到另一个表中。
然后运行一个审计过程,以确保员工最初输入的所有内容都可以在某个地方进行说明。该审计采用我们运行的 sql 查询的形式,它看起来像这样:
SELECT *
FROM [StaffEntry] s with (nolock)
LEFT JOIN [MainFrame] m with (nolock)
ON m.ItemNumber = s.ItemNumber
AND m.Customer=s.Customer
AND m.CustomerPO = s.CustomerPO -- purchase order
AND m.CustPORev = s.CustPORev -- PO revision number
LEFT JOIN [Rejected] r with (nolock) ON r.OrderID = s.OrderID
WHERE s.EntryDate BETWEEN @StartDate AND @EndDate
AND r.OrderID IS NULL AND m.MainFrameOrderID IS NULL
当然,这是经过大量修改的,但我相信重要的部分都得到了体现。问题是这个查询开始需要很长时间才能运行,我正试图弄清楚如何加快它。
我很确定问题是从StaffEntry
表到MainFrame
表的 JOIN。由于两者都保存了自一开始(本系统中为 2003 年)以来的每个订单的数据,因此它们往往有点大。表中使用的OrderID
andEntryDate
值在StaffEntry
导入到大型机时不会保留,这就是连接稍微复杂一些的原因。最后,由于我要在MainFrame
表中查找不存在的记录,所以在执行 JOIN 之后,我们IS NULL
在 where 子句中有丑陋的东西。
该StaffEntry
表由 EntryDate(集群)索引,并在 Customer/PO/rev 上单独索引。 MainFrame
由客户和主机费用编号(集群,其他系统需要)和客户/PO/Rev 单独索引。 Rejected
根本没有索引,但它很小,测试表明这不是问题。
所以,我想知道是否有另一种(希望更快)方式可以表达这种关系?