SELECT TOP 1はクエリのパフォーマンスに悪影響を与えます。これを克服するdbaアクセス可能な方法はありますか?


13

運用アプリケーション(SQL Server 2014 Standardと通信するC#)には、以下のようなクエリがあります。ほとんどの場合、ミリ秒単位で実行されます。ただし、(特定の値の場合@Id)場合によっては非常に時間がかかり、1分ほどかかります。これはアプリのタイムアウトよりも長いため、ユーザーにとってアプリは失敗します。

"goes nuts"の場合、返される結果セットは他のすべてではないが多くの場合にそうであるように、正しく空です。

幸いなことに、これは実稼働環境と開発環境の両方で再現可能です。

開発者は、クエリから「TOP 1」を削除し、アプリが結果セットの余分な行を消費することを確認して、パフォーマンスの問題を解決すると言います。

クエリプランナーは、インデックスTOP 1が存在する場合はインデックスを提案しません。(開発中)。

クエリの変更とアプリの修正が進行中です。ロールアウトには時間がかかります。

私の質問:アプリが新しいクエリで変更される前に、この問題を克服するために、運用SQL Serverインスタンスをチューニングまたは微調整するDBAアクセス可能な方法はありますか?

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg ON apg.person_id = bi.person_id
  JOIN pplan ON pplan.plan_id = sub.plan_id
  JOIN product ON product.product_id = [plan].product_id 
  JOIN product_attribute ON product_attribute.product_id = product.product_id 
 WHERE apg.group_id = @Id
   AND apg.start_date < GETDATE()
   AND (apg.end_date IS NULL OR apg.end_date > GETDATE()) 
   AND (sub.end_date IS NULL OR sub.end_date > GETDATE()) 
   AND product_attribute.attribute_type = 'special feature' 
   AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;

サブクエリとして試しましたか?例えば、([TOP1のないクエリの残りの部分]を選択からトップ1 subscription_idを選択
SeanR

おそらく、「通常の」クエリチューニングが機能するでしょうか。インデックスが十分に魅力的であれば、スキャンは終了します。それは計画ガイドよりも侵襲的ではありません。
usr

それで、同じ値が@ID 常に「気違い」になりますか?その場合、それらの値のいずれかを使用してテストし、実際のクエリプランをキャプチャします。それは何が悪いのかを教えてくれます。「悪い」値に一貫性がない場合、これはパラメータースニッフィング(解決策については@MartinSmithの回答を参照)であるか、クライアントが実際に結果セットを要求して消費する方法に関係するロックの問題である可能性があります。
RBarryYoung

回答:


12

クエリを変更できない場合は、プランガイドを使用できます。

クエリのパフォーマンスをテストしますOPTION (QUERYTRACEON 4138)sysadminこれを試すには権限を持つ人が必要です)。

満足のいくパフォーマンスが得られる場合は、プランガイドを使用してこれを適用できます。満足のいくパフォーマンスが得られない場合は、役立つヒントを見つけてください。おそらくOPTION (HASH JOIN, MERGE JOIN)不適切なネストされたループが問題である場合。USE PLAN N'...'ヒントに頼る必要があるかもしれません。

必要なヒントがわかったら、こちらの情報を使用してそれらを適用できます。


OPTION (QUERYTRACEON 4138)トリックをしました。ありがとう。次に、プランガイドの整理に進みます。
O.ジョーンズ

0

笑顔のためにこれを試してください
`>は> =に変更されているので、まったく同じクエリではありません

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi 
        ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg 
        ON apg.person_id = bi.person_id 
       AND apg.group_id = @Id
       AND apg.start_date < GETDATE()
       AND isnnull(apg.end_date, GETDATE()) >= GETDATE()             
  JOIN pplan 
        ON pplan.plan_id = sub.plan_id
       AND isnnull(sub.end_date, GETDATE()) >= GETDATE()
  JOIN product 
        ON product.product_id = [plan].product_id 
  JOIN product_attribute 
        ON product_attribute.product_id = product.product_id 
       AND product_attribute.attribute_type = 'special feature' 
       AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;

「クエリの変更とアプリの修正が進行中です。ロールアウトには時間がかかります。」OPは、パフォーマンスを「現状のまま」修正するソリューションを探しています。
マーティンスミス

@MartinSmithそして、彼らが修正を展開するとき、これはより良い修正かもしれません。アプリに余分な行を消費させることは、他のプログラムの変更です。
パパラッチ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.