0

这是需要很长时间的脚本

USE [r_prod]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      Drew Borden
-- Create date: 4/16/2009
-- Description: Procedure to populated subdivision extract table
-- =============================================
IF EXISTS(SELECT * FROM sys.procedures WHERE name='sp_extract_subdivision')
BEGIN
    DROP PROCEDURE sp_extract_subdivision
END
GO

CREATE PROCEDURE sp_extract_subdivision 
    @subdivsion_cd char(2) 
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

declare @strap varchar(25)

-- Clear existing record
delete from dbo.subdivision_extract

-- Select list of straps to loop through
declare strapList cursor for
select strap from dbo.parcel where county_cd = @subdivsion_cd

--Loop through straps and populate extract table values
BEGIN TRY
    OPEN strapList
    FETCH NEXT FROM strapList INTO @strap
    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @strap IS NOT NULL
        BEGIN
            insert into dbo.subdivision_extract (acct_num) values (RTRIM(@strap))
            exec sp_extract_parcel @strap
            exec sp_extract_detail @strap
            exec sp_extract_lnd_c @strap
            exec sp_extract_parcel_flg @strap
            exec sp_extract_owner @strap
            exec sp_extract_mail @strap
            exec sp_extract_legal_ln @strap
            exec sp_extract_site @strap 
            exec sp_extract_condo_unit @strap
            exec sp_extract_personal_x @strap
            exec sp_extract_personal_x_dist @strap
            exec sp_extract_phase_in @strap
            exec sp_extract_p_tax_dist @strap
            exec sp_extract_parcel_rel @strap
            exec sp_extract_entzone @strap
            exec sp_extract_dates @strap
            exec sp_extract_sales @strap
            exec sp_extract_sale_dtl @strap
            exec sp_extract_pchar @strap
            exec sp_extract_protest @strap

        END
        FETCH NEXT FROM strapList INTO @strap
    END
    CLOSE strapList
    DEALLOCATE strapList
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() as ErrorNumber, 
            ERROR_MESSAGE() as ErrorMessage,
            ERROR_PROCEDURE() as ExecutingProcedure,
            ERROR_LINE() as LineNumber
    CLOSE strapList
    DEALLOCATE strapList        
END CATCH
END
GO

有什么办法可以加快这个速度吗?

4

5 回答 5

1

这里真正的问题是您通过游标顺序调用 20 个存储过程。

我一开始就讨厌游标,并在以前的项目中为此提出了解决方案。

不是从游标中获取变量,您是否能够为所有数据按顺序运行 20 个存储过程?

我建议有一个临时表,其中包含数据的主键和一个状态整数,显示哪些已处理以及到哪一点。然后可以调用每个存储过程以处理所有行。

如果你真的想把它做好,让每个存储过程进程一次说 5% 的行,然后在循环之前使用 WAITFOR 允许一个小暂停,直到每个阶段处理完所有记录。如果每个进程的进程时间是合理的,它将确保锁仍然可以分配给其他进程,因此更重要的进程不会因为无法获取锁而超时。

需要多长时间delete from dbo.subdivision_extract?如果需要一段时间并且不需要日志(并且表上没有触发器),请尝试将其更改为TRUNCATE TABLE dbo.subdivision_extract

TLDR:重新开发存储过程以处理所有数据,然后您只需调用 20 个存储过程一次。

于 2009-11-06T18:04:49.453 回答
1

加快这一速度的最佳方法是编写您对每一行调用的存储过程的版本,以便它们针对整个集合运行,并完全放弃您的游标。否则,您可能会从将光标指定为 FORWARD_ONLY 中获得一点好处,但我看不出还有什么可以做的。

于 2009-11-06T12:22:41.973 回答
0

如果您将数据提取到文本文件中,您应该自己以基于集合的方式执行此操作,或者至少使用 SSIS。为每一行运行多个存储过程的游标是您可以用于此类事情的绝对最糟糕的方法。我敢打赌,您可以在 SSIS 包中执行此操作,并且只需几分钟而不是 9 小时。

于 2009-11-06T18:14:25.077 回答
0

是的,实际上非常容易修复:测量慢的部分,然后优化慢的部分。

您发布的只是一个 T-SQL 脚本,它在性能方面尽可能不透明。一个 DELETE、一个 SELECT、一个带有 INSERT 的游标迭代和一堆 EXEC。问题可能出在其中的任何地方,因此最好的解决方案是衡量并查看问题可能出在哪里。

获取脚本并PRINT GETDATE();在开始时添加一个,在 DELETE 之后,在第一个 FETCH 之后,然后在每个 EXEC 之后并执行一次迭代(删除循环内的 FETCH)。查看 PRINT 输出,您可以从中推断出执行每个步骤所需的时间。他们中的任何一个都脱颖而出吗?

附加 Profiler 并监视事件SP:StmtCompleted,并在 Duration 上使用过滤器。再次运行提取循环的单次迭代。哪些陈述在持续时间中最突出?

在 SSMS 中为单次迭代运行脚本,但选中工具栏中的 Include Actual Execution Plan 按钮。在结果执行展示中,哪些语句相对于批处理而言成本较高?

你必须缩小你的问题范围,因为它是无法诊断的脚本,这个脚本中没有完成任何实际工作,它只是调用其他程序来完成工作。一旦您确定了此脚本调用的过程中的实际慢语句,那么您应该再次发布,给出有问题的确切语句和数据的确切模式(包括所有索引定义),并针对特定问题寻求解决方案。

虽然从理论上讲,面向集合的处理可能比游标具有更好的性能,但实际上可能不可能编写一条语句来提取与 20 个存储过程执行调用相同的信息,除非这些过程是极其微不足道的单个 SELECT。

于 2009-11-06T18:31:25.887 回答
0

您正在为此存储的每个循环调用几个存储过程。我不知道其他人在做什么,但似乎他们也在查询/修改少量数据。您应该考虑将存储的数据合并到一个数据块中,并在多条记录的块中执行查询,而不是为每个表带循环。

于 2009-11-06T12:15:17.523 回答