为什么这些SQL查询之间的速度差异?

时间:2017-03-31 16:04:54

标签: sql sql-server join runtime where

我正在尝试编写一个查询来筛选我们的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秒。

1 个答案:

答案 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条件。

由于所有这些过滤,第二个条件在更少的行上运行,并且代码运行得更快。通常在加入之前进行过滤是一个好主意,但这个规则肯定有例外。