2014-11-14 164 views
0

我有一个存储过程在应用程序中运行。它通常在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 
+0

你真的需要NOLOCK?你有遗漏和/或重复的数据吗? – 2014-11-14 17:48:04

+0

另外我注意到你正在强制索引提示......这可能是一个非常糟糕的选择,因为你告诉编译器,你比sql知道的更多关于用于查询的索引。这应该是最后的手段。 – 2014-11-14 17:51:05

回答

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)) 
相关问题