游标查询速度慢,但单个查询速度很快

时间:2012-07-25 19:25:31

标签: sql sql-server tsql stored-procedures

我有一个存储过程,它接受三个参数并使用游标来收集数据。奇怪的是运行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

1 个答案:

答案 0 :(得分:0)

显然, 你创造了一个临时表 你需要4倍于临时表的最小值 的 1。选择查询执行时间
2.在Cursor中插入查询执行时间 3.在TempTeble + Cursor运行时插入查询执行时间
4.选择Temeptable Execution time,与1

相同

尝试删除光标并选择带有连接但不带游标的查询 有可能生成这样的sql select查询