由于内部联接和左联接,SQL查询速度慢吗?
谁能解释这种行为或者如何解决?
如果执行此查询:
select * from TblA left join freetexttable ( TblB, *, 'query' ) on TblA.ID = [Key] inner join DifferentDbCatalog.dbo.TblC on TblA.ID = TblC.TblAID
这将非常非常非常慢。
如果将查询更改为使用两个内部联接而不是左联接,则查询速度将非常快。如果将其更改为使用两个左联接而不是内部联接,则速度将非常快。
如果我们还使用sql表变量而不是freetexttable,则可以观察到相同的行为。
每当我们有一个表变量(或者freetexttable)和一个不同数据库目录中的表时,就会出现性能问题,其中一个在内部联接中,另一个在左联接中。
有谁知道为什么这么慢,或者如何加快速度?
解决方案
回答
索引用于执行联接的字段。
一个好的经验法则是为任何通常引用的外键或者候选键分配一个索引。
回答
通常,我们应该打开"显示实际执行计划"选项,然后仔细查看导致速度下降的原因。 (将鼠标悬停在每个联接上以查看详细信息)我们将要确保获得的是索引查找而不是表扫描。
我假设发生的事情是,为了执行连接之一,SQL被迫将所有内容从一张表中拉到内存中。有时,颠倒我们加入表的顺序也会有所帮助。
回答
一般的经验法则是,OUTER JOIN导致结果集中的行数增加,而INNER JOINs导致结果集中的行数减少。当然,在很多情况下,情况也相反,但是以这种方式工作的可能性更大。我们想要做的就是保持结果集(工作集)的大小尽可能小。
由于两个联接在第一个表上都匹配,因此更改顺序不会影响结果的准确性。因此,我们可能想在LEFT JOIN之前执行INNER JOIN:
SELECT * FROM TblA INNER JOIN DifferentDbCatalog.dbo.TblC on TblA.ID = TblC.TblAID LEFT JOIN freetexttable ( TblB, *, 'query' ) on TblA.ID = [Key]
实际上,无论我们为联接指定了哪个顺序,查询优化器都应该足够聪明以进行编译以使用更快的选项。但是,最好假装我们有一个笨拙的查询优化器,并且查询操作是按顺序进行的。这有助于将来的维护人员发现有关表性质的潜在错误或者假设。
因为优化器应该重新编写代码,所以这可能不足以完全解释我们所看到的行为,因此我们仍然需要检查用于每个查询的执行计划,并可能按照前面的建议添加索引。但是,这仍然是一个很好的学习原则。
回答
如果在执行计划中反复调用freetexttable(TblB,*,'query')
到临时表中,则可能会有所帮助。