存储过程运行速度很快但速度很慢

时间:2014-11-14 17:40:47

标签: sql-server sql-server-2008 stored-procedures

我有一个在应用程序中运行的存储过程。它通常在500毫秒内完成,但有时可能需要5秒。如何消除5秒运行?非常感谢任何帮助。

--Table definition:

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID (N'[dbo].[EventValue]') AND type in (N'U'))
DROP TABLE [dbo].[EventValue]
GO

CREATE TABLE [dbo].[EventValue](
    [MetricId] [int] NOT NULL,
    [AttributeId] [int] NOT NULL,
    [DataRunId] [int] NOT NULL,
    [CurrentDataTime] [bigint] NOT NULL,
    [AType] [bit] NOT NULL,
    [Mm] [int] NOT NULL,
    [ReceivedDataTime] [bigint] NOT NULL,
    [ValueList] nvarchar(4000) NULL,
    [MState] [int] NULL,
    [OId] [int] NULL,
    [EventStartTime] [bigint] NULL,
    [EventEndTime] [bigint] NULL,
    [EventEST] [bigint] NOT NULL,
    [EventEE] [int] NULL
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_EventValue_DataRunId_EventEndTime] ON [dbo].[EventValue] 
(
    [DataRunId] ASC,
    [EventEndTime] ASC
)
INCLUDE ( [CurrentDataTime]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

CREATE CLUSTERED INDEX [IX_EventValue_DataRunId_CurrentDataTime ] ON [dbo].[EventValue] 
(
    [DataRunId] ASC,
    [CurrentDataTime] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [IX_EventValueEventEST] ON [dbo].[EventValue] 
(
    [EventEST] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DataRun]') AND type in (N'U'))
DROP TABLE [dbo].[DataRun]
GO

CREATE TABLE [dbo].[DataRun](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [PersonId] [uniqueidentifier] NOT NULL,
    [WallTime] datetime2(7) NOT NULL,
    [DataTimeSeed] [bigint] NOT NULL,
CONSTRAINT [PK_TimeMapping] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

)ON [PRIMARY]     GO

 --Stored procedure:
CREATE PROC [dbo].[Event_Get]
    @PersonId UNIQUEIDENTIFIER,
    @startTime relativeTime,
    @duration BigInt ,   -- in milliSeconds
    @storageBlock int  -- in milliSeconds

AS
BEGIN

DECLARE @EventValueResultSet TABLE
(
    [MetricId] [int] NOT NULL,
    [AttributeId] [int] NOT NULL,
    [CurrentDataTime] [bigint] NOT NULL,
    [AType] [bit] NOT NULL,
    [Mm] [int] NOT NULL,
    [ReceivedDataTime] [bigint] NOT NULL,
    [CompressedValueList] varbinary(8000) NULL,
    [ValueList] nvarchar(4000) NULL,
    [MState] [int] NULL,
    [OId] [int] NULL,
    [EventStartTime] [bigint] NULL,
    [EventEndTime] [bigint] NULL,
    [EventEE] [int] NULL,
    [DataRunSeed] [bigint] NOT NULL,
    [DataRunWallTime] datetime2(7) NOT NULL 
)

DECLARE @endTime bigint = @startTime + @duration;
DECLARE @blockStartTime  bigint = 0;

With C2(CurrentDataTime ) AS
(
    SELECT MIN(CurrentDataTime )  
    FROM  dbo.EventValue WV WITH (NOLOCK)
    INNER JOIN dbo.DataRun_ DR WITH (NOLOCK)
        ON WV.DataRunId = DR.Id AND DR.PersonId = @PersonId
    WHERE CurrentDataTime  > (@startTime - @storageBlock) 
        AND CurrentDataTime  < @startTime
)
SELECT @blockStartTime  = ISNULL(CurrentDataTime , @startTime) FROM C2;

-- Events between @startTime and @endTime
 INSERT INTO @EventValueResultSet
    (MetricId, AttributeId, CurrentDataTime, AType, 
    Mm, ReceivedPhysioDataTime, ValueList,
    MState, OId, EventStartTime, EventEndTime, EventEE,
    DataRunSeed, DataRunWallTime)
 SELECT MetricId, AttributeId, CurrentDataTime , AType,
    Mm, ReceivedPhysioDataTime, ValueList, 
    MState, OId, EventStartTime, EventEndTime, EventEE,
    DR.DataTimeSeed, DR.WallTime
FROM dbo.EventValue EV WITH (NOLOCK)
INNER JOIN dbo.DataRun_ DR WITH (NOLOCK)
    ON EV.dataRunId = DR.Id
    AND DR.PersonId = @PersonId
WHERE PhysioCurrentDataTime  BETWEEN @blockStartTime  AND @endTime

-- Events started before @startTime and active in duration, including
-- (1) events that started before @startTime and have not ended (endTime = 0)
-- (2) events that started before @startTime and ended after @startTime
INSERT INTO @EventValueResultSet
    (MetricId, AttributeId, CurrentDataTime , AType, 
    Mm, ReceivedPhysioDataTime, ValueList,
    MState, OId, EventStartTime, EventEndTime, EventEE,
    DataRunSeed, DataRunWallTime)
SELECT MetricId, AttributeId, CurrentDataTime , AType,
    Mm, ReceivedDataTime, ValueList, 
    MState, OId, EventStartTime, EventEndTime, EventEE,
    DR.DataTimeSeed, DR.WallTime        
FROM dbo.EventValue EV WITH
     (NOLOCK,INDEX(IX_EventValueDataRunId_EventEndTime))
INNER JOIN dbo.DataRun_ DR WITH (NOLOCK)
    ON EV.dataRunId = DR.Id
    AND DR.PersonId = @PersonId
WHERE (CurrentDataTime  < @blockStartTime )
AND (EventEndTime = 0 OR EventEndTime >= @blockStartTime )  

--
-- Other Statements using @EventValueResultSet
--

SELECT * FROM @EventValueResultSet ORDER BY MetricId, CurrentDataTime
END

1 个答案:

答案 0 :(得分:0)

将两个插件合并为单个插件,如下所示

INSERT INTO @EventValueResultSet(....)
SELECT ....
       ....
FROM   dbo.EventValue EV WITH (NOLOCK))
       INNER JOIN dbo.DataRun_ DR WITH (NOLOCK)
               ON EV.dataRunId = DR.Id
                  AND DR.PersonId = @PersonId
WHERE  PhysioCurrentDataTime BETWEEN @blockStartTime AND @endTime
        OR ( ( CurrentDataTime < @blockStartTime )
             AND ( EventEndTime = 0
                    OR EventEndTime >= @blockStartTime ) )