查询在SQL 2005与SQL 2008R2上的运行方式不同


9

在我的办公室,我们有一个非常丑陋的查询,但在生产环境和开发环境(分别为20秒和4秒)中运行得很好。但是,在我们的测试环境中,它需要4个小时以上。SQL2005(+最新补丁程序)正在生产和开发中。SQL2008R2正在测试中。

我看了一下查询计划,它表明SQL2008R2通过表假脱机(惰性假脱机)使用TempDB来存储从链接服务器返回的行。下一步显示嵌套循环(左半连接)占用了查询的96.3%。两家运营商之间的界限为5,398MB!

SQL 2005的查询计划不使用tempdb,也不使用左反半联接。

下面是经过清理的代码,执行计划顶部是2005年计划,底部是2008R2。

是什么导致急剧的减速和变化?我期望看到一个不同的执行计划,所以这不会打扰我。查询时间的急剧下降是困扰我的原因。

由于2008R2版本使用的是tempdb,因此我是否必须查看底层硬件,所以我必须查看如何优化其用法?

有没有更好的方法来编写查询?

谢谢您的帮助。

    INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT 
 Table1.iGroupID,
 GETDATE()
FROM Table1
WHERE 
 NOT EXISTS (
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE 
   (
    Alias2.FirstName + Alias2.LastName = dbo.fnRemoveNonLetter(Table1.FullName)
    AND NOT dbo.fnRemoveNonLetter(Table1.FullName) IS NULL
    AND NOT Alias2.FirstName IS NULL 
    AND NOT Alias2.LastName  IS NULL
   ) OR (
    Alias2.FamilyName = dbo.fnRemoveNonLetter(Table1.FamilyName)
    AND Alias2.Child1Name = dbo.fnRemoveNonLetter(Table1.Child1Name)
    AND NOT dbo.fnRemoveNonLetter(Table1.FamilyName) IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.Child1Name) IS NULL
    AND NOT Alias2.Familyname IS NULL
    AND NOT Alias2.Child1Name IS NULL
   ) OR (
    Alias2.StepFamilyName = dbo.fnRemoveNonLetter(Table1.StepFamilyName)
    AND Alias2.StepFamilyNameChild1 = dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2)
    AND NOT Alias2.StepFamilyName IS NULL
    AND NOT Alias2.StepFamilyNameChild1 IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyName) IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2) IS NULL
   )  
 ) AND NOT EXISTS (
  SELECT 1
  FROM Table3
  INNER JOIN Table4
   ON Table4.FirstNameType = Table3.FirstNameType 
  INNER JOIN table5
   ON table5.LastNameType = Table3.LastNameType 
  WHERE 
   Table3.iGroupID = Table1.iGroupID
   AND Table3.bIsClosed = 0
   AND Table4.sNameTypeConstant = 'new_lastname'
   AND table5.sFirstNameConstant = 'new_firstname'
 )

SQL-2005


SQL2008R2

::编辑:: 从不同的SQL2005实例执行查询,该执行计划与“好实例”几乎相同。仍然不确定两个2005版本在2008R2链接服务器上的运行情况如何好于2008R2实例到2008R2实例的运行情况。

虽然我不否认代码可以使用一些工作,但是如果代码是问题所在,我是否会在所有试用中看到相同的执行计划?不论SQL版本如何?

::编辑:: 我已经将SP1和CU3应用于两个2008R2实例,但仍然没有骰子。我专门在链接服务器中设置了搭配,没有骰子。我专门将我的用户acct的权限设置为在两个实例上均为sysadmin,没有骰子。我还记得我的sql server 2008内部和疑难解答,我们将看看我是否可以对此进行跟踪。

感谢大家的帮助和提示。

::编辑:: 我对链接服务器进行了各种权限更改。我使用过SQL登录名,域登录名,已经模拟了用户,并且使用了“使用此安全上下文进行”选项。我在链接服务器的两边都创建了对服务器具有sysadmin权限的用户。我没主意。

我仍然想知道为什么SQL2005执行查询的原因与SQL2008R2截然不同。如果查询不好,我将在SQL2005和SQL2008R2上看到4小时以上的运行时间。

Answers:


5

我希望您重新查询。

您存在可保存性问题,甚至在那里使用标量函数调用,这也将损害查询。您可能要在Table2上创建一个FullName计算列,并在其上放置一个索引,确保您的索引包含FirstName和LastName。您还应该添加索引以帮助其他

另外,制作一个内联表值函数来执行您的“ RemoveNonLetter”功能,并重新整理您的查询以使用它,可能就像我在这里所做的那样使用APPLY。

并绝对检查Paul的答案 所指的那个错误。

INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT 
 Table1.iGroupID,
 GETDATE()
FROM Table1
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.FullName)) AS fn (FullName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.FamilyName)) AS famn (FamilyName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.Child1Name)) AS c1n (Child1Name)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.StepFamilyName)) AS sfn (StepFamilyName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.StepFamilyNameChild2)) AS sfnc2 (StepFamilyNameChild2)
WHERE 
 NOT EXISTS (
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.FullName = fn.FullName
  UNION ALL
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.FamilyName = famn.FamilyName AND Alias2.Child1Name = c1n.Child1Name
  UNION ALL
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.StepFamilyName = sfn.StepFamilyName AND Alias2.StepFamilyNameChild1 = sfnc2.StepFamilyNameChild2
 ) 
 AND NOT EXISTS (
  SELECT 1
  FROM Table3
  INNER JOIN Table4
   ON Table4.FirstNameType = Table3.FirstNameType 
  INNER JOIN table5
   ON table5.LastNameType = Table3.LastNameType 
  WHERE 
   Table3.iGroupID = Table1.iGroupID
   AND Table3.bIsClosed = 0
   AND Table4.sNameTypeConstant = 'new_lastname'
   AND table5.sFirstNameConstant = 'new_firstname'
 )
;

6

除了先前的答案之外,计划回归的原因可能是由于当计划包含“反半联接”时已知的基数估计错误。参见知识库文章2222998

假设2005年计划产生了令人满意的性能,您可能会发现将服务器升级到包含该修复程序的版本(并启用TF4199激活它)将使您返回“良好”计划。

也就是说,还有很多其他机会可以改善该查询,因此这可能是一个专注于执行此查询的好时机。


5

我建议将远程数据本地化,因为

  1. 链接服务器设置(例如排序规则)不同
  2. 尽管链接服务器设置,本地排序规则与远程排序规则不同
  3. 由于权限的原因,查询无法正常远程运行

对于第1点,请参见sp_serveroption;
对于第2点,还请检查服务器/数据库排序规则。

对于第3点,请从Linchi Shea中查看以下内容:

根据我在这里的回答,您正在要求SQL Server在本地处理所有数据: 在视图中使用OPENQUERY对性能的影响

编辑

再来看一遍,我看到“好”计划上有2个远程呼叫,而不是一个。这证实了我在这里所说的


抱歉,很长的延迟。1:我检查了链接服务器的设置,它们是相同的。2:我还检查了链接服务器属性,并将其隐式设置为远程服务器。3:我仍在进行A / B测试的安全上下文。我仍然坚持完全不同的执行计划背后的逻辑。从R2服务器到R2服务器,它仅运行select(拉入超过15万行),然后进行联接。与2005 R2一样,它在进行选择,并加入远程服务器。两种方案的安全性上下文都是相同的。
RateControl 2011年

3

从datagod的“尝试重写查询”注释上+1。

我还想知道您是否遇到导致此速度下降的链接服务器端的权限问题。不久前,我写了一篇有关此链接服务器速度下降的博客。可能值得验证权限(它是一个SQL链接服务器吗?还是另一个DBMS?如果是后者,那么无论如何您将无法获得大量的统计信息)

您是否仍在测试环境上使用SQL Server 2005来尝试此查询并排除该环境?

升级以来您是否重建了统计信息?


3

这种比较有很多问题...我只是不知道从哪里开始。

  1. 获取适合您的生产和测试机器的规格。

  2. 确定两种环境中各种链接服务器之间的网络链接。他们是一样的速度吗?在这两种环境中,服务器是否彼此并排放置?

  3. 有什么办法可以重写查询以不使用链接服务器?在服务器之间连接表会使您容易受到拓扑更改的影响,在大多数情况下,他的速度非常慢。

  4. 使用NOT和OR通常会导致全表扫描。尝试重写查询。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.