2017-02-23 60 views
0

我不确定我能否提供足够的答案详细信息,但是我的公司在旧版mssql视图中遇到了性能问题。我将它缩小到了右外连接,但我不熟悉每个连接没有“开”的连接结构,如下面的代码片段所示。堆叠连接性能差

如何在下面编写连接以提高性能或简化格式在Field1上加入表名称= field2格式?

FROM dbo.tblObject AS tblObject_2 
      JOIN dbo.tblProspectB2B PB ON PB.Object_ID = tblObject_2.Object_ID 
      RIGHT OUTER JOIN dbo.tblProspectB2B_CoordinatorStatus 
      RIGHT OUTER JOIN dbo.tblObject 
      INNER JOIN dbo.vwDomain_Hierarchy 
      INNER JOIN dbo.tblContactUser 
      INNER JOIN dbo.tblProcessingFile WITH (NOLOCK) 
      LEFT OUTER JOIN dbo.enumRetentionRealization AS RR ON RR.RetentionRealizationID = dbo.tblProcessingFile.RetentionLeadTypeID 
      INNER JOIN dbo.tblLoan 
      INNER JOIN dbo.tblObject AS tblObject_1 WITH (NOLOCK) ON dbo.tblLoan.Object_ID = tblObject_1.Object_ID ON dbo.tblProcessingFile.Loan_ID = dbo.tblLoan.Object_ID ON dbo.tblContactUser.Object_ID = dbo.tblLoan.ContactOwnerID ON dbo.vwDomain_Hierarchy.Object_ID = tblObject_1.Domain_ID ON dbo.tblObject.Object_ID = dbo.tblLoan.ContactOwnerID ON dbo.tblProspectB2B_CoordinatorStatus.Object_ID = dbo.tblLoan.ReferralSourceContactID ON tblObject_2.Object_ID =  dbo.tblLoan.ReferralSourceContactID 
+1

'RIGHT OUTER JOIN'和'LEFT OUTER JOIN'需要一个'ON'子句,就像普通的'JOIN'一样(或者在WHERE子句中表之间的关系必须存在,这被认为是不好的形成)。此外,外部连接的工作方式与内部连接不同,因此如果您不确定其工作方式,最好在切换到“JOIN”(这是“INNER JOIN”的简写)之前了解它们。我怀疑在你的'WHERE'子句中,你可以找到加入的表之间的关系,这里省略了'ON'。 – JNevill

+0

在视图中,您确实有两个选项,将查询重写为使用子查询连接而不是连接到整个表,或确保适当的索引就位(索引视图或基础表)。 –

+0

这个视图没有Where子句。以前的DBA在许多视图(和存储过程)上广泛使用了这种堆叠联接系统。我从来没有见过它。对于每个“加入”,我总是看到一个“ON”,所以我有点难过。 我很确定转移到派生查询是要走的路,但我没有得到这个堆叠连接的东西。 –

回答

2

您最后的INNER JOIN有多个ON陈述。根据this的问题和答案,这样的语法相当于嵌套的子查询。

+0

这只是连接语法(100%标准SQL)的一种变体:'FROM a JOIN b JOIN c ON b.id = c.id ON a.id = c.id'与 完全相同'FROM b JOIN c ON b.id = c.id JOIN a ON a.id = c.id',连接按ONs的顺序逻辑执行。 – dnoeth

-1

这是我见过的最糟糕的问题之一。由于我无法弄清楚如何在没有底层数据的情况下工作,这就是我建议给你的。

首先找到一个很好的样本贷款,并写一个查询来对付这个视图来返回loan_id = ...现在你有一个数据集,你可以更容易地检查你的变化,可能是数百万记录返回。确保这些结果是有意义的(正确加入tbl_objects困扰我,因为它是没有意义的返回所有对象记录)

现在开始用你认为应该是第一个表格写你的查询(我会建议贷款是第一个表,如果它不是,那么第一个表是Object留下来加入贷款))和贷款ID的where子句。 检查您的结果,您是否使用where子句添加的视图查询获得了相同的贷款信息?

然后逐个添加一个连接,查看它对查询的影响以及结果是否显示偏离轨迹。一旦你找出了一个查询结果,并添加了所有表格的结果,那么你可以尝试其他几个贷款ID来检查。一旦这些检查出来,然后运行没有where子句的整个查询,并检查视图结果(如果它是一个很大的数字,你可能需要看看记录计数是否匹配,并通过视觉检查(使用order by by both为了确保你的结果是相同的顺序)在这个过程中,尽量只使用左连接,而不是右连接和左连接的组合(它可以让内部单独连接) 我使它成为一种习惯复杂的查询先完成所有的内部连接,然后再连接左边的连接,我从不在生产代码中使用正确的连接 现在你已经准备好进行性能调整了。它返回整个表,并且该表名的性质以及其他连接到同一个表的表导致我相信他可能想要一个左连接。不知道数据的含义,很难确定。因此,首先如果您要为一个贷款ID返回太多记录,那么请考虑真正的问题是,随着表的增长,返回太多记录已成为问题。

另外考虑到你可以经常使用视图并用代码替换它以获得相同的结果。调用视图的视图是一种糟糕的技术,通常会导致性能问题。通常其他视图顶部的视图会调用相同的表格,因此当您不需要时,您最终会多次加入它们。

根据您拥有的数据库后端检查您的解释计划或执行计划。对此的分析应该显示您可能缺少索引的位置。

还要确保查询中的每个表都是必需的。当您加入视图时尤其如此。该视图可能会连接到其他12个表,但您只需要其中一个表的数据,并且它可以连接到其中一个表。确保你没有使用select *,但只返回视图实际需要的字段。你有内部连接,所以根据定义,选择*正在返回你不需要的字段。

如果您选择的部分视图具有不同的内容,那么请考虑是否可以通过更改为派生表或添加where子句来清除您获得的多个记录,这些记录是独特的。要查看导致倍数的原因,您可能需要暂时使用select *来查看所有列,并找出哪一个不是唯一的并导致问题。

这整个过程不会轻松或有趣。只要慢慢采取行动,谨慎而有条不紊地进行工作,你就会到达那里,最终得到一个可理解和可维护的查询。