简体   繁体   中英

Cursor Query Slow, But Individual Queries Fast

I have a stored procedure that accepts three parameters and uses cursors to gather data. The strange thing is the amount of time that it takes to run the SP. At times it will take 5-10 minutes to run and return back only 300 rows. By running the individual queries within the cursors the data seems to return very quickly. I'm a little stumped as to why running it as a whole takes so long. If anyone can point out any mistakes or fixes I may need to may to my query it would be greatly appreciated.

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

Obviously, You create a temptable you need 4 times more minimal for temp table
1. Select Query Execution time
2. Insert Query Execution time in Cursor
3. Insert Query Execution time in TempTeble+Cursor runtime
4. Select Temeptable Execution time same as 1

Try to remove cursor and select your query with joins not with cursors it may be possible to generate such sql select query

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM