1

制約を追加するとパフォーマンスが大幅に低下する、一見単純なクエリ ケースがあります。AND 句で制約されている 3 つの列はすべて bigint です。そのうちの 2 つ (ただし 3 つすべてではない) を使用すると、クエリは即座に実行されますが、3 つ目の 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

これは、これらの 3 つの列すべてが 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]))

...そして、2 つの 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 に答える