0

パフォーマンスに関して質問があります。現在、テーブルの行がすでに数百万のレコードにある場合、クエリのパフォーマンスに問題があるテーブルがあります。

これはテーブルです:

CREATE TABLE [dbo].[HistorySampleValues]
(
    [HistoryParameterID] [int] NOT NULL,
    [SourceTimeStamp] [datetime2](7) NOT NULL,
    [ArchiveTimestamp] [datetime2](7) NOT NULL CONSTRAINT [DF__HistorySa__Archi__2A164134]  DEFAULT (getutcdate()),
    [ValueStatus] [int] NOT NULL,
    [ArchiveStatus] [int] NOT NULL,
    [IntegerValue] [bigint] SPARSE  NULL,
    [DoubleValue] [float] SPARSE  NULL,
    [StringValue] [varchar](100) SPARSE  NULL,
    [EnumNamedSetName] [varchar](100) SPARSE  NULL,
    [EnumNumericValue] [int] SPARSE  NULL,
    [EnumTextualValue] [varchar](256) SPARSE  NULL
) ON [PRIMARY]

CREATE CLUSTERED INDEX [Source_HistParameterID_Index] ON [dbo].[HistorySampleValues]
(
    [HistoryParameterID] ASC,
    [SourceTimeStamp] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

と のクラスター化インデックスでかなりフラットHistoryParameterIDですSourceTimeStamp

これは私が使用しているストアドプロシージャです

   SET NOCOUNT ON;
   DECLARE @SqlCommand NVARCHAR(MAX)

   SET @SqlCommand = 'SELECT HistoryParameterID, 
                            SourceTimestamp, ArchiveTimestamp,ValueStatus,ArchiveStatus,
                            IntegerValue,DoubleValue,StringValue,EnumNumericValue,
                            EnumTextualValue,EnumNamedSetName 
                        FROM [HistorySampleValues] WITH(NOLOCK) 
                        WHERE ([HistoryParameterID] =' + @ParamIds + '
                        AND
                        [SourceTimeStamp] >= ''' + CONVERT(VARCHAR(30),@StartTime, 25) + '''
    AND           
    [SourceTimeStamp] <= ''' + CONVERT(VARCHAR(30),@EndTime, 25) + ''') 
    AND ValueStatus = ' + @ValueStatus 

    EXECUTE( @SqlCommand )

ご覧のとおり、HistoryParameterIDSourceTimestampが最初のクエリのパラメーターとして使用されています。そして、約 28k レコードである 8 時間分のレコードを取得すると、1.8 秒 - 700 ミリ秒という不安定なパフォーマンスで返されます。

デザインはスケーリングしますか?770 億レコードに達するたびに? または使用する戦略はありますか?SQL Server のバージョンは Standard Edition であるため、パーティション分割や列ストアは使用されません。または、SQL Server Standard Edition の最大パフォーマンスに達しましたか?


これは更新されたストアド プロシージャです

 @ParamIds int,
    @StartTime datetime,
    @EndTime datetime,
    @ValueStatus int 
AS
BEGIN
       SET NOCOUNT ON;
       SELECT HistoryParameterID, 
        SourceTimestamp, ArchiveTimestamp,ValueStatus,ArchiveStatus,
        IntegerValue,DoubleValue,StringValue,EnumNumericValue,
        EnumTextualValue,EnumNamedSetName 
        FROM [HistorySampleValues] WITH(NOLOCK) 
        WHERE 
        HistoryParameterID = @ParamIds
        AND (SourceTimeStamp >= @StartTime AND SourceTimeStamp <=@EndTime)
        AND (@ValueStatus = -1 OR ValueStatus = @ValueStatus)

テーブル内の 41213 行から 849600000 行までを取得するのに、1.396 秒のクライアント処理時間がかかりました。

これを改善する方法はありますか?

4

1 に答える 1

0

新しい SQL コマンドを実行するたびに、MS SQL Server でコンパイルする必要があります。コマンドを再利用すると、コンパイル時間を節約できます。このようなストアド プロシージャでコマンドを直接実行する必要があります。これにより、コンパイルが可能になり、より一貫した結果が得られます。

SELECT ... 
WHERE ([HistoryParameterID] = @ParamIds 
AND [SourceTimeStamp] >= @StartTime
AND [SourceTimeStamp] <= @EndTime 
AND ValueStatus = @ValueStatus 

これにより、コマンドのパフォーマンスを監視する機会も得られます。

于 2014-12-08T08:59:56.183 に答える