0

テーブル (1000 万以上の行) を対象とする既存のストアド プロシージャを確認/リファクタリングする必要があります。ストアド プロシージャの署名は簡単には変更できず、以下のようになります。

ストアド プロシージャは、パイプで区切られた 2 つの文字列を取得し、SQL 関数 ( SplitDelimitedVarChar) を使用して文字列を一時テーブルに分割します。この一時テーブルは、実際の選択で使用されます。配列string内の文字列の数は、1 から千までの範囲です。

DateValueおよびTimeValue列にはint、行のタイムスタンプの表現が含まれています。

私の質問は、これが良い(最良の)解決策であるか、それとももっとうまくできるかどうか、誰かがアイデアを持っているかどうかです。主な問題は、速度を最適化できるかどうかです。

テーブルはこのストアド プロシージャを介してのみアクセスされるため、インデックスは列でクラスター化されておらず、WHEREすべてのSELECT列が含まれています。

提案や指針をありがとう。

CREATE PROCEDURE [dbo].[spdata_Get_Ana]
@beginTime INT,
@endTime INT,
@subscribers VARCHAR(MAX),
@exchanges VARCHAR(MAX) = '1:',
@beginDateValue int, 
@endDateValue int,
@target int = 1
AS  
BEGIN
SET NOCOUNT ON;

CREATE TABLE #exch (Item Varchar(20) COLLATE database_default)
INSERT INTO #exch
SELECT Item FROM [SplitDelimitedVarChar] (@exchanges, '|') ORDER BY Item
CREATE CLUSTERED INDEX idx ON #exch (Item)

CREATE TABLE #subs (Item Varchar(20) COLLATE database_default)
INSERT INTO #subs
SELECT Item FROM [SplitDelimitedVarChar] (@subscribers, '|') ORDER BY Item
CREATE CLUSTERED INDEX idx ON #subs (Item)

SELECT 
   [Id]
  ,'' AS 'Name'
  ,[NameId]
  ,[Level]
  ,[Ne]
  ,[CallId]
  ,[Bg]
  ,[DateTime]
  ,[TimeStamp]
  ,[LogOwnerSnb]
  ,[TypeOfLog]
  ,[AbsenceCode]
  ,[AnswerTime]
  ,[CallForwardingReason]
  ,[CallForwardingToNumber]
  ,[CallTransferTime]
  ,[CallTransferReason]
  ,[SeizedSubscriberType]
  ,[SeizedSubscriberTime]
  ,[SeizedSubscriberNumber]
  ,[CalledSubscriberService]
  ,[InSubscriberType]
  ,[InSubscriberNumber]
  ,[CallDirection]
  ,[SubscriberService]
  ,[ClearingCause]
  ,[ClearingCauseTime]
  ,[OnHookTime]
  ,[OutAnswerSubType]
  ,[OutAnswerTime]
  ,[OutAnswerSubNum]
  ,[RingingStartedTime]
  ,[ReroutedToNumber]
  ,[InitiatedService]
  ,[B26]
FROM [dbo].[data_centrex_Ana] AS A
WHERE
    (A.[DateValue] BETWEEN @beginDateValue AND @endDateValue)
AND
    EXISTS(SELECT [Item] FROM #exch WHERE [Item] = A.[Level])
AND
    (A.[TimeValue] BETWEEN @beginTime AND @endTime)
AND
(
   (@target = 1 AND EXISTS(SELECT [Item] FROM #subs WHERE [Item] = A.[LogOwnerSnb]))
   OR
   (@target = 2 AND EXISTS(SELECT [Item] FROM #subs WHERE [Item] = A.[Bg]))
)
END
4

1 に答える 1

1

選択した列をインデックスに含めることには何らかの利点があるとは思えません。
それだけで大きなインデックスになります。

ジョインとして試す

SELECT [Id]  
FROM [dbo].[data_centrex_Ana] AS A 
JOIN #exch   
 ON [Item] = A.[Level] 
JOIN #subs    
  ON (@target = 1 AND [Item] = A.[LogOwnerSnb])   
  OR (@target = 2 AND [Item] = A.[Bg]) 
WHERE
     (A.[DateValue] BETWEEN @beginDateValue AND @endDateValue) 
AND  (A.[TimeValue] BETWEEN @beginTime AND @endTime)
于 2012-10-30T13:22:27.460 に答える