为什么这个访问查询需要这么长时间?

时间:2016-03-28 03:02:49

标签: sql excel performance ms-access access-vba

我写了一个访问客户端来对两个excel文件进​​行比较。它将两个要比较的excel文件加载到临时表中,并根据下面显示的两个查询对它们进行评估。

有两个查询,因为有时其中一个excel文件只有一个名称列。基本上,用户输入要比较的列的名称,我们会根据该列更改查询。

第一个查询cQueryFull可以完美而快速地工作(仅需几秒钟即可完成超过100k的记录)。第二个查询cQueryPart按预期工作(就比较而言),但从未在具有超过5,000条记录的表上完成。它最终挂了几个小时,我被迫关闭该程序。

我不明白为什么一个查询比另一个查询快得多,我希望有人能够帮助我解决它并可能修复第二个查询。我的访问客户端创建查询的部分如下:

If chkOneColumn.Value = 0 Then
    ' Construct Comparison Query
    qString = "SELECT OriginalFile." & txtOriginalFirst.Value & " as OriginalFirstName, OriginalFile." & txtOriginalMiddle.Value & " as OriginalMiddleName, OriginalFile." & txtOriginalLast.Value & " as OriginalLastName, WorkingFile." & txtWorkingFirst.Value & " as WorkingFirstName, WorkingFile." & txtWorkingMiddle.Value & " as WorkingMiddleName, WorkingFile." & txtWorkingLast.Value & " as WorkingLastName " _
            + "FROM OriginalFile, WorkingFile " _
            + "WHERE (OriginalFile." & txtOriginalFirst.Value & " not like WorkingFile." & txtWorkingFirst.Value & " or OriginalFile." & txtOriginalMiddle.Value & " not like WorkingFile." & txtWorkingMiddle.Value & " or OriginalFile." & txtOriginalLast.Value & " not like WorkingFile." & txtWorkingLast.Value & ") " _
            + "and OriginalFile." & txtOriginalAddress.Value & " = WorkingFile." & txtWorkingAddress.Value & " " _
            + "and OriginalFile." & txtOriginalDOB.Value & " = WorkingFile." & txtWorkingDOB.Value & " "

    ' Open the record set
    Set db = CurrentDb
    Set qd = db.CreateQueryDef("cQueryFull")
    With qd
        .ReturnsRecords = True
        .sql = qString
    End With
    DoCmd.OpenQuery "cQueryFull"
ElseIf chkOneColumn.Value = -1 Then
    ' Construct Comparison Query
    qString = "SELECT OriginalFile." & txtOriginalFirst.Value & " as OriginalName, IIF(WorkingFile." & txtWorkingFirst.Value & " is null, '', WorkingFile." & txtWorkingFirst.Value & ") + IIF(WorkingFile." & txtWorkingMiddle.Value & " is null, '', ' '+WorkingFile." & txtWorkingMiddle.Value & ") + IIF(WorkingFile." & txtWorkingLast.Value & " is null, '', ' '+WorkingFile." & txtWorkingLast.Value & ") as WorkingName " _
            + "FROM OriginalFile, WorkingFile " _
            + "WHERE (OriginalFile." & txtOriginalFirst.Value & " not like '*'+WorkingFile." & txtWorkingFirst.Value & "+'*' or OriginalFile." & txtOriginalFirst.Value & " not like '*'+WorkingFile." & txtWorkingMiddle.Value & "+'*' or OriginalFile." & txtOriginalFirst.Value & " not like '*'+WorkingFile." & txtWorkingMiddle.Value & "+'*') " _
            + "and OriginalFile." & txtOriginalAddress.Value & " like WorkingFile." & txtWorkingAddress.Value + " " _
            + "and OriginalFile." & txtOriginalDOB.Value & " like WorkingFile." & txtWorkingDOB.Value & " " _

    ' Open the record set
    Set db = CurrentDb
    Set qd = db.CreateQueryDef("cQueryPart")
    With qd
        .ReturnsRecords = True
        .sql = qString
    End With
    DoCmd.OpenQuery "cQueryPart"
End If

任何人都可以通过我的查询识别问题吗?如果它很重要,我已经尝试在构建和执行查询之前索引表。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

很难说,但我怀疑问题在于WHERE子句中的交叉连接和谓词量(以及谓词类型)。

像你一样加入两个表往往会创建一个非常大的集合,然后必须运行WHERE子句。此外,JET / ACE查询中的LIKE运算符可能是最慢的比较运算符。特别喜欢领先的通配符(*)。

有时候只是没有解决它,但有时将预先查询的部分加载到(另一个)临时表中并对该数据运行进一步的查询实际上更快。

有没有什么方法可以简化你的WHERE子句,或者以不同批次的方式识别谓词,以便你可以先运行更直接的查询,然后进一步处理这些结果? (我建议可能写入临时表并进一步查询,因为子查询已经过优化,并不一定能保证你编写的“sql逻辑”就像它实际运行的那样)。