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
你真的需要NOLOCK?你有遺漏和/或重複的數據嗎? – 2014-11-14 17:48:04
另外我注意到你正在強制索引提示......這可能是一個非常糟糕的選擇,因爲你告訴編譯器,你比sql知道的更多關於用於查詢的索引。這應該是最後的手段。 – 2014-11-14 17:51:05