1

我有一个看似简单的查询案例,其中添加约束会导致性能大幅下降。受 AND 子句约束的三列都是 bigint。如果我使用其中任何两个(但不是全部三个),查询会立即运行,但只要我添加第三个 AND,它就会运行缓慢。

WITH tb AS (SELECT
   DISTINCT u.*  
FROM
   [user] u  
INNER JOIN
   user_personal up 
      ON up.user_id = u.user_id        
WHERE
   1=1  
   AND u.site_instance_id = 1      
   AND u.graduation_class_id = 27  
   AND u.graduation_term_id IN (76,75) 
   ) SELECT
   COUNT (*) AS count 
FROM
   ( SELECT
      ROW_NUMBER() OVER (
   ORDER BY
      last_name ASC) AS row,
      * 
   FROM
      tb) sub

这是否与所有这三个列都是 bigint 的事实有关?还是与这些列上的表索引有关?(我没有为这些列设置任何索引)。或者它可能是别的东西?

注意 - 在这种情况下,AND u.site_instance_id = 1 是多余的,但没关系,不是吗?

编辑使用 SET showplan_all ON 后:

 |--Compute Scalar(DEFINE:([Expr1005]=CONVERT_IMPLICIT(int,[Expr1008],0)))
   |--Stream Aggregate(DEFINE:([Expr1008]=Count(*)))
        |--Nested Loops(Left Semi Join, WHERE:(.[dbo].[user].[user_id] as [u].[user_id]=.[dbo].[user_personal].[user_id] as [up].[user_id]))
             |--Clustered Index Scan(OBJECT:(.[dbo].[user].[PK__user__B9BE370F7F60ED59] AS [u]), WHERE:(.[dbo].[user].[site_instance_id] as [u].[site_instance_id]=(1) AND .[dbo].[user].[graduation_class_id] as [u].[graduation_class_id]=(27) AND (.[dbo].[user].[graduation_term_id] as [u].[graduation_term_id]=(75) OR .[dbo].[user].[graduation_term_id] as [u].[graduation_term_id]=(76))))
             |--Clustered Index Scan(OBJECT:(.[dbo].[user_personal].[PK__user_per__C701FAD641EDCAC5] AS [up]))

...并且只有两个 AND 子句...

|--Compute Scalar(DEFINE:([Expr1005]=CONVERT_IMPLICIT(int,[Expr1008],0)))
       |--Stream Aggregate(DEFINE:([Expr1008]=Count(*)))
            |--Hash Match(Left Semi Join, HASH:([u].[user_id])=([up].[user_id]), RESIDUAL:(.[dbo].[user].[user_id] as [u].[user_id]=.[dbo].[user_personal].[user_id] as [up].[user_id]))
                 |--Clustered Index Scan(OBJECT:(.[dbo].[user].[PK__user__B9BE370F7F60ED59] AS [u]), WHERE:(.[dbo].[user].[graduation_class_id] as [u].[graduation_class_id]=(27) AND (.[dbo].[user].[graduation_term_id] as [u].[graduation_term_id]=(75) OR .[dbo].[user].[graduation_term_id] as [u].[graduation_term_id]=(76))))
                 |--Clustered Index Scan(OBJECT:(.[dbo].[user_personal].[PK__user_per__C701FAD641EDCAC5] AS [up]))
4

2 回答 2

2

我仍然不确定我是否理解你的问题——@Hogan 有一个更简单的查询版本。尽管如此,您应该在您加入的每个字段以及您始终搜索的任何字段上都有索引。

在你的情况下,我会确保你有以下索引:

  • user.user_id(估计已经有PK了)
  • user_personal.user_id
  • user.site_instance_id、user.graduation_class_id 和 user.graduation_term_id

您也可以考虑分别为 WHERE 条件中的 3 个字段中的每一个添加索引,但这应该会产生更好的性能。另外,请改用@Hogan 的查询。

祝你好运。

于 2013-01-24T00:34:36.693 回答
1

这个故事一定还有更多。显然,以下代码与发布的代码相同且更简单(我希望更快):

  SELECT COUNT(DISTINCT u.user_id)) as count
  FROM [user] u  
  INNER JOIN  user_personal up ON up.user_id = u.user_id        
  WHERE
   u.site_instance_id = 1   AND   
   u.graduation_class_id = 27  AND
   u.graduation_term_id IN (76,75) 
于 2013-01-24T00:24:19.573 回答