1
我有一個存儲過程,它接受三個參數並使用遊標來收集數據。奇怪的是運行SP所需的時間。有時需要5-10分鐘才能運行並返回300行。通過在遊標內運行單個查詢,數據似乎很快返回。我有點難以理解爲什麼整體運行需要這麼長時間。如果任何人都可以指出我可能需要查詢的任何錯誤或修復,我將不勝感激。遊標查詢速度慢,但個別查詢速度快
USE [AW]
GO
/****** Object: StoredProcedure [dbo].[Issue_Report] Script Date: 07/25/2012 15:06:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Issue_Report]
@MinDate DateTime,
@MaxDate DateTime,
@PSNumParam varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Setup Temp Table
DECLARE @TempIssueData TABLE
(
[Date] datetime,
[SerialNum] varchar(MAX),
[LotNum] varchar(MAX),
[CatalogNum] varchar(MAX),
[PSNum] varchar(MAX),
[Description] varchar(MAX),
[ORCaseNum] varchar(MAX),
[UserName] varchar(MAX),
[Issued_From] varchar(MAX),
[Issued_To] varchar(MAX),
[Surgical_Specalty] varchar(MAX),
[surgeon] varchar(50),
[SurgeryEndDate] datetime
)
-- Declare Variables (easier for debugging)
DECLARE @StartDate datetime = @MinDate
DECLARE @EndDate datetime = @MaxDate
DECLARE @Date datetime
DECLARE @SurgeryEndDate datetime
DECLARE @SerialNum varchar(MAX)
DECLARE @LotNum varchar(MAX)
DECLARE @CatalogNum varchar(MAX)
DECLARE @PSNum varchar(MAX)
DECLARE @Description varchar(MAX)
DECLARE @ORCaseNum varchar(MAX)
DECLARE @UserName varchar(MAX)
DECLARE @Issued_From varchar(MAX)
DECLARE @Issued_To varchar(MAX)
DECLARE @Surgical_Specialty varchar(MAX)
DECLARE @Surgeon varchar(50)
DECLARE @ItemID uniqueidentifier
DECLARE @LocationID uniqueidentifier
DECLARE @UserID uniqueidentifier
DECLARE @UnitLocation uniqueidentifier
-- Fix EndDateTime to include the whole day
IF(SELECT CONVERT(varchar,@MaxDate, 108) AS TimeOnly) = '00:00:00'
BEGIN
SET @EndDate = DATEADD(SECOND, 86400,@MaxDate)
END
-- Setup Parameters
IF (@PSNumParam ='') BEGIN SET @PSNumParam = NULL END
-- Setup Cursor
DECLARE curs_GetIssueData CURSOR FOR
SELECT item.ID, item.SerialNumber, item.LotNumber, items.PartNumber, items.CrossRefID, items.Description, item.LocationID
FROM dbo.item WITH (INDEX(Stat_LastUpdated)) INNER JOIN dbo.items ON item.ItemID = items.ID
WHERE (dbo.item.Stat = 3) AND (dbo.item.LastUpdated BETWEEN @StartDate AND @EndDate) AND Tracking='1'
AND CrossRefID = ISNULL(@PSNumParam, CrossRefID)
OPEN curs_GetIssueData
-- Start Reading
FETCH NEXT FROM curs_GetIssueData INTO @ItemID, @SerialNum, @LotNum, @CatalogNum, @PSNum, @Description, @LocationID
WHILE (@@FETCH_STATUS = 0)
-- BEGIN WHILE
BEGIN
SET @Issued_From = NULL
BEGIN
SELECT @Issued_From = ISNULL(Locations.Name, 'N/A')
FROM dbo.Locations
WHERE Locations.ID = @LocationID
END
BEGIN
-- Setup Cursor
DECLARE curs_GetTransData CURSOR FOR
SELECT TOP 1 ORCaseNumber, SurgicalSpecialty, UserID, ORNumber, TransDate, Surgeon, EndDateTime
FROM dbo.transactions
WHERE transactions.ItemID = @ItemID AND transactions.TransactionTypeID in (8,9,10) AND transactions.TransDate BETWEEN @StartDate and @EndDate
ORDER BY transactions.TransDate desc
OPEN curs_GetTransData
-- Start Reading
FETCH NEXT FROM curs_GetTransData INTO @ORCaseNum, @Surgical_Specialty, @UserID, @Issued_To, @Date, @Surgeon, @SurgeryEndDate
WHILE (@@FETCH_STATUS = 0)
-- BEGIN GetTransData WHILE
BEGIN
-- Reset UserName
SET @UserName = NULL
SET @UnitLocation = NULL
BEGIN
SELECT @UnitLocation = Unit.LocationID
FROM dbo.Unit
WHERE UnitType='4' and Unit.LocationID = @LocationID
END
-- Check to see if UserID is NULL
IF @UserID IS NULL AND @UnitLocation IS NOT NULL
BEGIN
SET @UserName = 'CORONA'
END
ELSE
BEGIN
SELECT @UserName = dbo.users.LastName + ', ' + dbo.users.FirstName
FROM dbo.users
WHERE users.ID = @UserID
END
FETCH NEXT FROM curs_GetTransData INTO @ORCaseNum, @Surgical_Specialty, @UserID, @Issued_To, @Date, @Surgeon, @SurgeryEndDate
-- END GetTransData WHILE
END
-- CLEANUP
CLOSE curs_GetTransData
DEALLOCATE curs_GetTransData
END
BEGIN
INSERT INTO @TempIssueData
VALUES(
@Date,
@SerialNum,
@LotNum,
@CatalogNum,
@PSNum,
@Description,
@ORCaseNum,
@UserName,
@Issued_From,
@Issued_To,
@Surgical_Specialty,
@Surgeon,
@SurgeryEndDate
)
END
-- Fetch next record
FETCH NEXT FROM curs_GetIssueData INTO @ItemID, @SerialNum, @LotNum, @CatalogNum, @PSNum, @Description, @LocationID
-- END WHILE
END
-- CLEANUP
CLOSE curs_GetIssueData
DEALLOCATE curs_GetIssueData
SELECT * FROM @TempIssueData ORDER BY [Date] Desc, [Issued_From]
END
你檢查了[實際查詢執行計劃](http://www.simple-talk.com/sql/performance/execution-plan-基本/)? (如果沒有數據洞察力,以及確切哪部分緩慢,這很難回答。) – Andomar 2012-07-25 19:28:46
嵌套遊標?哦,我的,哦,我的,哦,我的。至少將遊標聲明更改爲'DECLARE CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY FOR ...' – 2012-07-25 19:29:02
檢查查詢計劃。如果它們不同,你可能會處理不良的參數嗅探。如果是這樣,你可以A)嘗試添加WITH RECOMPILE或B)聲明臨時變量,填入那些臨時變量中的參數,然後僅使用臨時變量。 – Stu 2012-07-25 19:29:09