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
4

1 回答 1

0

显然,您创建了一个临时表,对于临时表
1. 选择查询执行时间
2. 在光标中
插入查询执行时间 3. 在 TempTeble+Cursor 运行时中插入查询执行时间
4. 选择与 1 相同的临时表执行时间

尝试删除游标并使用连接而不是游标选择您的查询,它可能会生成这样的 sql 选择查询

于 2014-09-04T20:31:25.697 回答