我正在尝试编写一个查询来筛选我们的ERP数据库,当我删除过滤条件时,我发现速度非常奇怪。
这就是之前的查询(完成时间不到一秒钟,通常会返回10到数百条记录,具体取决于订单和项目)
SELECT TOP 1000 jobmat.job, jobmat.suffix, jobmat.item, jobmat.matl_qty,
jobmat.ref_type, jobmat.ref_num, spec.NoteContent, spec.NoteDesc,
job.ord_num, jobmat.RowPointer
FROM jobmat
INNER JOIN ObjectNotes AS obj ON obj.RefRowPointer = jobmat.RowPointer
INNER JOIN SpecificNotes AS spec ON obj.SpecificNoteToken = spec.SpecificNoteToken
INNER JOIN job ON job.job = jobmat.job AND job.suffix = jobmat.suffix
WHERE ord_num LIKE '%3766%' AND ref_type = 'P' AND
(spec.NoteDesc LIKE '%description%' OR spec.NoteContent LIKE '%COMPANY%DWG%1162402%')
这也是我改变WHERE声明的原因:
WHERE ord_num LIKE '%3766%' AND ref_type = 'P' AND
spec.NoteContent LIKE '%COMPANY%DWG%1162402%'
在进行此修改后运行它会使我的运行时间达到9秒(通常返回1-3条记录)。有没有明显的理由让我失踪?我原以为同样应该大致相同。非常感谢任何帮助!
编辑:我已多次运行此查询的两个版本进行测试,运行时间相当一致; <版本1为1秒,版本2为~9秒。
答案 0 :(得分:0)
原始查询在返回结果集之前必须找到1000个匹配的行。它是通过基于JOIN
创建结果集然后根据WHERE
子句进行过滤来实现的。
条件:
(spec.NoteDesc LIKE '%description%' OR spec.NoteContent LIKE '%COMPANY%DWG%1162402%')
匹配的行数多于:
(spec.NoteContent LIKE '%COMPANY%DWG%1162402%')
因此,第二个版本必须经过并处理更多行才能获得1,000个匹配。
这就是第二个版本较慢的原因。
如果您希望第二个版本看起来更快,可以添加ORDER BY
子句。这需要在两种情况下读取所有数据。因为ORDER BY
会占用与匹配行数相关的额外时间,所以您可能会看到第二行比第一行略快。一个警告:两者至少需要9秒钟。
编辑:
我喜欢上面的解释,但如果在两种情况下都处理了所有行,那么它可能不正确。这是另一种解释,但更具推测性。
这取决于NoteContent
非常长,因此LIKE
会对查询效果产生明显影响。第二个版本可能是"优化"通过将过滤子句推送到读取数据的处理中的节点。这是SQL Server定期执行的操作。这意味着在第二种情况下,所有数据正在处理LIKE
。
由于OR
条件,第一个示例无法将过滤推向该级别。然后,NoteDescription
上的条件以多种方式短路:
WHERE
条件。LIKE
条件。由于所有这些过滤,第二个条件在更少的行上运行,并且代码运行得更快。通常在加入之前进行过滤是一个好主意,但这个规则肯定有例外。