2008-09-11 5 views
3

SQL Serverには、以下のコードに従って構成されている従来のシステムから継承されたテーブルがあります。私は、テーブル作成ステートメントの下のコードに記述されているように、テーブルを照会するSPを作成しました。私の問題は、散発的に、.NETからEnterprise Library 4とDataReaderオブジェクトの両方を介してこのSPに呼び出しが遅いことです。 SPは、データオブジェクト内のループ構造を介して呼び出され、ユーザーオブジェクトを設定する目的でSPに入るパラメータを指定します。また、ループ構造を通過するたびに遅い呼び出しが行われないことも重要です。それは一般的には1日以上の間は大丈夫ですし、プレゼンテーションを開始するとデバッグが非常に難しくなります。.NETアプリケーションからSQL Serverへの散発的な呼び出しが遅い

この表には、約500万行が含まれています。たとえば、低速のコールは10秒ほどかかりますが、高速のコールは平均して0〜10ミリ秒かかります。私は、遅い呼び出しの間にロック/ブロックトランザクションをチェックしたが、どれも見つからなかった。私は、コール時間を監視するために、データレイヤーにカスタムパフォーマンスカウンターをいくつか作成しました。基本的に、パフォーマンスが悪い場合は、その1つのコールでは本当に悪いです。しかし、それが良い時、それは本当に良いです。私はいくつかの異なるデベロッパーマシンで問題を再現できましたが、開発とステージングのデータベースサーバーには問題がありませんでした。一般的に、この問題はSQLサーバーサービスの再起動によって解決されますが、必ずしもそうではありません。私が照会しているフィールドのテーブルにはインデックスがありますが、私が望むよりも多くのインデックスがあります。しかし、私は、レガシーシステムに与える可能性がある影響により、索引を持っている物やおもちゃを削除することを躊躇しています。これまでに誰かがこのような問題を経験したことがありますか、それともそれを改善するための勧告がありますか?

CREATE TABLE [dbo].[product_performance_quarterly](
    [performance_id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL, 
    [product_id] [int] NULL, 
    [month] [int] NULL, 
    [year] [int] NULL, 
    [performance] [decimal](18, 6) NULL, 
    [gross_or_net] [char](15) NULL, 
    [vehicle_type] [char](30) NULL, 
    [quarterly_or_monthly] [char](1) NULL, 
    [stamp] [datetime] NULL CONSTRAINT [DF_product_performance_quarterly_stamp] DEFAULT (getdate()), 
    [eA_loaded] [nchar](10) NULL, 
    [vehicle_type_id] [int] NULL, 
    [yearmonth] [char](6) NULL, 
    [gross_or_net_id] [tinyint] NULL, 
CONSTRAINT [PK_product_performance_quarterly_4_19_04] PRIMARY KEY CLUSTERED 
(
    [performance_id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
SET ANSI_PADDING OFF 
GO 
ALTER TABLE [dbo].[product_performance_quarterly] WITH NOCHECK ADD CONSTRAINT [FK_product_performance_quarterlyProduct_id] FOREIGN KEY([product_id]) 
REFERENCES [dbo].[products] ([product_id]) 
GO 
ALTER TABLE [dbo].[product_performance_quarterly] CHECK CONSTRAINT [FK_product_performance_quarterlyProduct_id] 

CREATE PROCEDURE [eA.Analytics.Calculations].[USP.GetCalculationData] 
(
    @PRODUCTID INT,      --products.product_id 
    @BEGINYEAR INT,      --year to begin retrieving performance data 
    @BEGINMONTH INT,     --month to begin retrieving performance data 
    @ENDYEAR INT,      --year to end retrieving performance data 
    @ENDMONTH INT,      --month to end retrieving performance data 
    @QUARTERLYORMONTHLY VARCHAR(1),  --do you want quarterly or monthly data? 
    @VEHICLETYPEID INT,     --what product vehicle type are you looking for? 
    @GROSSORNETID INT     --are your looking gross of fees data or net of fees data? 
) 
AS 
BEGIN 

    SET NOCOUNT ON 

    DECLARE @STARTDATE VARCHAR(6), 
      @ENDDATE VARCHAR(6), 
      @vBEGINMONTH VARCHAR(2), 
      @vENDMONTH VARCHAR(2) 

IF LEN(@BEGINMONTH) = 1 
    SET @vBEGINMONTH = '0' + CAST(@BEGINMONTH AS VARCHAR(1)) 
ELSE 
    SET @vBEGINMONTH = @BEGINMONTH 

IF LEN(@ENDMONTH) = 1 
    SET @vENDMONTH = '0' + CAST(@ENDMONTH AS VARCHAR(1)) 
ELSE 
    SET @vENDMONTH = @ENDMONTH 

SET @STARTDATE = CAST(@BEGINYEAR AS VARCHAR(4)) + @vBEGINMONTH 
SET @ENDDATE = CAST(@ENDYEAR AS VARCHAR(4)) + @vENDMONTH 

--because null values for gross_or_net_id and vehicle_type_id are represented in 
--multiple ways (true null, empty string, or 0) in the PPQ table, need to account for all possible variations if 
--a -1 is passed in from the .NET code, which represents an enumerated value that 
--indicates that the value(s) should be true null. 

IF @VEHICLETYPEID = '-1' AND @GROSSORNETID = '-1' 
    SELECT 
     PPQ.YEARMONTH, PPQ.PERFORMANCE 
    FROM PRODUCT_PERFORMANCE_QUARTERLY PPQ 
     WITH (NOLOCK) 
    WHERE 
     (PPQ.PRODUCT_ID = @PRODUCTID) 
     AND (PPQ.YEARMONTH BETWEEN @STARTDATE AND @ENDDATE) 
     AND (PPQ.QUARTERLY_OR_MONTHLY = @QUARTERLYORMONTHLY) 
     AND (PPQ.VEHICLE_TYPE_ID IS NULL OR PPQ.VEHICLE_TYPE_ID = '0' OR PPQ.VEHICLE_TYPE_ID = '') 
     AND (PPQ.GROSS_OR_NET_ID IS NULL OR PPQ.GROSS_OR_NET_ID = '0' OR PPQ.GROSS_OR_NET_ID = '') 
    ORDER BY PPQ.YEARMONTH ASC 

IF @VEHICLETYPEID <> '-1' AND @GROSSORNETID <> '-1' 
    SELECT 
     PPQ.YEARMONTH, PPQ.PERFORMANCE 
    FROM PRODUCT_PERFORMANCE_QUARTERLY PPQ 
     WITH (NOLOCK) 
    WHERE 
     (PPQ.PRODUCT_ID = @PRODUCTID) 
     AND (PPQ.YEARMONTH BETWEEN @STARTDATE AND @ENDDATE) 
     AND (PPQ.QUARTERLY_OR_MONTHLY = @QUARTERLYORMONTHLY) 
     AND (PPQ.VEHICLE_TYPE_ID = @VEHICLETYPEID) 
     AND (PPQ.GROSS_OR_NET_ID = @GROSSORNETID) 
    ORDER BY PPQ.YEARMONTH ASC 

IF @VEHICLETYPEID = '-1' AND @GROSSORNETID <> '-1' 
    SELECT 
     PPQ.YEARMONTH, PPQ.PERFORMANCE 
    FROM PRODUCT_PERFORMANCE_QUARTERLY PPQ 
     WITH (NOLOCK) 
    WHERE 
     (PPQ.PRODUCT_ID = @PRODUCTID) 
     AND (PPQ.YEARMONTH BETWEEN @STARTDATE AND @ENDDATE) 
     AND (PPQ.QUARTERLY_OR_MONTHLY = @QUARTERLYORMONTHLY) 
     AND (PPQ.VEHICLE_TYPE_ID IS NULL OR PPQ.VEHICLE_TYPE_ID = '0' OR PPQ.VEHICLE_TYPE_ID = '') 
     AND (PPQ.GROSS_OR_NET_ID = @GROSSORNETID) 
    ORDER BY PPQ.YEARMONTH ASC 

IF @VEHICLETYPEID <> '-1' AND @GROSSORNETID = '-1' 
    SELECT 
     PPQ.YEARMONTH, PPQ.PERFORMANCE 
    FROM PRODUCT_PERFORMANCE_QUARTERLY PPQ 
     WITH (NOLOCK) 
    WHERE 
     (PPQ.PRODUCT_ID = @PRODUCTID) 
     AND (PPQ.YEARMONTH BETWEEN @STARTDATE AND @ENDDATE) 
     AND (PPQ.QUARTERLY_OR_MONTHLY = @QUARTERLYORMONTHLY) 
     AND (PPQ.VEHICLE_TYPE_ID = @VEHICLETYPEID) 
     AND (PPQ.GROSS_OR_NET_ID IS NULL OR PPQ.GROSS_OR_NET_ID = '0' OR PPQ.GROSS_OR_NET_ID = '') 
    ORDER BY PPQ.YEARMONTH ASC 

END 

答えて

0

別のクエリがテーブルをロックしているし、それは私はこれが古くなっていたインデックスで起こる見てきました

1

を完了するために、あなたの罪のないクエリが単に待っているバックグラウンドで実行されているような音。また、ストアドプロシージャに入ってくるさまざまなパラメータに対して異なるクエリプランが使用されている、パラメータスニッフィングの問題でもあります。

低速コールのパラメータを取得し、低速コールが実行されるたびに同じものであるかどうかを確認する必要があります。

チューニングウィザードを実行して、インデックスを推奨するかどうかを確認することもできます。

更新や挿入が遅すぎること(インデックスの変更に必要な時間+ロック/競合)が発生するか、ディスク容量が不足していることを証明できるまで、インデックスが多すぎることを心配したくはありません。それら。

0

奇妙なエッジケースですが、最近遭遇しました。

クエリがアプリケーションで実行される時間がManagement Studioから実行される時間より長い場合、Arithabortがオフになっていることを確認することをお勧めします。 Management Studioで使用される接続パラメータは、.NETで使用される接続パラメータとは異なります。

+0

私もこれを見ましたが、それをオフに設定すると問題が逆転することになります(高速クエリは遅くなります)。私が物事に影響を与えるために私が知っている唯一の理由は、別の計画が選択されているパラメータスニッフィングに関連しています。 –

+0

私はその問題に遭遇していません。それをオフに設定すると、実際にSMSが実行されているものと同じになります。これが問題の最初の発見方法です。 – Josef

0

スローコールのパラメータは、ファーストコールよりも何らかの方法で異なり、インデックスも使用できないか、ロックの種類がありますあなたを抱き締めている競合。特定のプロセスがハングアップしている間にロックをブロックしていないことを確認したとしたら、それは最初のプロセスであることを示唆しています。ただし、ステージングサーバー(このエラーを再現できないこと)と開発サーバー(再現可能なサーバー)は同じデータベース構成を使用していることを確認してください。たとえば、「READ COMMITTED SNAPSHOT」が本番環境では有効になっているが、開発環境では有効になっていない可能性があります。

パラメータの違いがある場合は、SQLプロファイラを使用してトランザクションを監視し、いくつかのものをキャプチャすることをお勧めします - 遅いものと速いものをいくつか取り込み、その後Management StudioウィンドウでそのSP上記のパラメータ値を入力し、 "Control-L"を押して実行計画を取得します。これは、SQL Serverがクエリを処理する方法を正確に示しています。異なるパラメータの組み合わせの実行計画を比較して、1つのセットとの違いがあるかどうかを確認し、そこから最適化することができます。

幸運を祈る!