2

我有一个非常简单的查询,这让我非常抓狂。

情况如下:

  • 我有两个数据库服务器。
  • 一种是旧的 SQL Server 2000 (VM),资源非常少。
  • 另一个是一个非常大的 SQL Server 2005 企业集群,拥有绝对荒谬的可用资源。
  • 我有一小部分在 3 秒内执行并在 SQL Server 2000 上返回 50,000 多行数据的较大查询
  • 在 SQL Server 2005 上,同样的小查询需要 15 分钟以上才能返回 1000 行
  • 我正在使用的数据库是这两台服务器上的镜像。相同的表,相同的表中的数据,相同的表索引等。

我尝试在 SQL Server 2005 表上创建不同的索引,对所有存在的索引进行碎片整理,更新表统计信息等。没有什么能让这个查询在 SQL Server 2005 上运行得更快。目前没有针对 SQL 运行其他任何东西Server 2005 服务器,我们的 DBA 向我保证,这不是配置问题或与 SQL Server 2000 和 SQL Server 2005 之间的功能弃用有关。

查询如下:

SELECT (CASE 
             WHEN TeamMember.ID IN  (SELECT DISTINCT ProjMgrID FROM ProjMgr)
                THEN 'Yes' 
                ELSE 'No' 
        END) AS OnProjAsMgr 
FROM TeamMember

因此,返回所有 ProjMgrs 的不同列表,如果 TeamMember 在该列表中,则将“是”分配给 OnProjAsMgr 值。

我是一个 SQL 新手,这是前任编写的代码。我不知道是否有更好的编写方法,但我不明白为什么它在 SQL Server 2000 上运行良好,但在 SQL Server 2005 上完全崩溃。

4

3 回答 3

5

DISTINCT 导致排序,IN 导致对整个查询求值。这个版本是如何工作的:

SELECT OnProjAsMgr = CASE WHEN EXISTS 
  (SELECT 1 FROM dbo.ProjMgr WHERE ProjMgrID = TeamMember.ID)
  THEN 'Yes' 
  ELSE 'No' 
  END
FROM dbo.TeamMember;

如果情况没有那么好,那么我怀疑索引丢失了,没有它们,任何查询都不会很好地执行。

于 2012-09-11T20:38:43.917 回答
1

我不知道“更好”的方式,但您可以尝试另一种方式:

SELECT ... other fields you want ...,
       CASE WHEN ProjMgr.ProjMgrID IS NULL
            THEN 'No'
            ELSE 'Yes'
        END AS OnProjAsMgr
  FROM TeamMember
  LEFT
 OUTER
  JOIN ProjMgr
    ON ProjMgr.ProjMgrID = TeamMember.ID
;

笔记:

  • 在某些 DBMS 上,这将比您的查询执行得更好,但我不知道它是否会在 SQL Server 2005 上执行得更好,因为您的查询已经在 SQL Server 2000 上运行良好。我认为您只需要尝试它。
  • 您的查询使用SELECT DISTINCT ProjMgrID FROM ProjMgr. 如果这实际上不同于SELECT ProjMgrID FROM ProjMgr- 也就是说,如果实际上存在重复的ProjMgrIDin值ProjMgr- 那么上述查询并不完全等同于您的查询,因为它将为每个重复项提供单独的记录。在这种情况下,您可能必须添加一个GROUP BY子句。
  • 就此而言,如果正如我怀疑的那样,如果SELECT DISTINCT ProjMgrID FROM ProjMgr相当于SELECT ProjMgrID FROM ProjMgr您的数据,那么也可能值得删除DISTINCT,因为这也可能会影响优化器。
于 2012-09-11T20:38:30.240 回答
-1
SELECT (
    CASE WHEN P.ID IS NULL THEN 'No' ELSE 'Yes' END
) AS OnProjAsMgr
FROM TeamMember AS T 
LEFT OUTER JOIN ProjMgr AS P ON T.ID=P.ID
于 2012-09-11T20:41:31.033 回答