【问题标题】:Can I spread out a long running stored proc accross multiple CPU's?我可以将长时间运行的存储过程分散到多个 CPU 上吗?
【发布时间】:2010-03-05 17:05:53
【问题描述】:

[也在超级用户上-https://superuser.com/questions/116600/can-i-spead-out-a-long-running-stored-proc-accross-multiple-cpus]

我在 SQL Server 中有一个存储过程,可以获取并解密数据块。 (在这种情况下是信用卡。)

在大多数情况下,性能是可以忍受的,但有几个客户的过程非常缓慢,需要 1 分钟才能完成。 (确切地说,从 SQL Server 返回 59377 毫秒,但根据负载可能会有几百毫秒的变化)

当我观察这个过程时,我发现 SQL 只使用一个 proc 来执行整个过程,而且通常只使用 proc 0。

有没有一种方法可以更改我的存储过程,以便 SQL 可以多线程处理该过程?作弊并将通话分成两半(前 50%,后 50%)并分散负载是否可行? (这里只是吐痰)

我的存储过程:

USE [Commerce]
GO
/****** Object:  StoredProcedure [dbo].[GetAllCreditCardsByCustomerId]    Script Date: 03/05/2010 11:50:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetAllCreditCardsByCustomerId]
@companyId UNIQUEIDENTIFIER, @DecryptionKey NVARCHAR (MAX)
AS
SET NoCount ON

DECLARE @cardId uniqueidentifier
DECLARE @tmpdecryptedCardData VarChar(MAX);
DECLARE @decryptedCardData VarChar(MAX);

    DECLARE @tmpTable as Table 
    (
        CardId uniqueidentifier,
        DecryptedCard NVarChar(Max)
    )

DECLARE creditCards CURSOR FAST_FORWARD READ_ONLY
  FOR  Select cardId from CreditCards where companyId = @companyId and Active=1 order by addedBy desc



--2 
OPEN creditCards
--3 
FETCH creditCards INTO @cardId   -- prime the cursor

WHILE @@Fetch_Status = 0 
  BEGIN

        --OPEN creditCards
        DECLARE creditCardData CURSOR FAST_FORWARD READ_ONLY
                        FOR select convert(nvarchar(max), DecryptByCert(Cert_Id('Oh-Nay-Nay'), EncryptedCard, @DecryptionKey)) FROM CreditCardData where cardid = @cardId order by valueOrder

                OPEN creditCardData

                FETCH creditCardData INTO @tmpdecryptedCardData   -- prime the cursor

                WHILE @@Fetch_Status = 0 
                    BEGIN               

                        print 'CreditCardData'
                        print @tmpdecryptedCardData                     

                        set @decryptedCardData = ISNULL(@decryptedCardData, '') + @tmpdecryptedCardData
                        print '@decryptedCardData'
                        print @decryptedCardData;

                        FETCH NEXT FROM creditCardData INTO @tmpdecryptedCardData   -- fetch next
                    END 
                    CLOSE creditCardData
                    DEALLOCATE creditCardData       

                    insert into @tmpTable (CardId, DecryptedCard) values (  @cardId, @decryptedCardData )
                    set @decryptedCardData = ''


    FETCH NEXT FROM creditCards INTO @cardId   -- fetch next
  END

select CardId, DecryptedCard FROM @tmpTable


CLOSE creditCards
DEALLOCATE creditCards

【问题讨论】:

标签: sql-server multithreading sql-server-2008 stored-procedures performance


【解决方案1】:

在单个相关子查询中使用 FOR XML 进行连接怎么样:

DECLARE @cards TABLE
    (
     cardid INT NOT NULL
    ,addedBy INT NOT NULL
    )
DECLARE @data TABLE
    (
     cardid INT NOT NULL
    ,valueOrder INT NOT NULL
    ,encrypted VARCHAR(MAX) NOT NULL
    )

INSERT  INTO @cards
VALUES  ( 0, 1 )
INSERT  INTO @cards
VALUES  ( 1, 0 )

INSERT  INTO @data
VALUES  ( 0, 0, '0encrypted0' )
INSERT  INTO @data
VALUES  ( 0, 1, '0encrypted1' )
INSERT  INTO @data
VALUES  ( 0, 2, '0encrypted2' )
INSERT  INTO @data
VALUES  ( 1, 0, '1encrypted0' )
INSERT  INTO @data
VALUES  ( 1, 1, '1encrypted1' )

-- INSERT INTO output_table ()
SELECT  cardid, decrypted
FROM    @cards AS cards
        OUTER APPLY ( SELECT    REPLACE(encrypted, 'encrypted', 'decrypted') + '' -- Put your UDF here
                      FROM      @data AS data
                      WHERE     data.cardid = cards.cardid
                      ORDER BY  data.valueOrder
                    FOR
                      XML PATH('')
                    ) AS data ( decrypted )
ORDER BY cards.addedBy DESC

【讨论】:

  • 我没有意愿针对 OP 中存储过程的恐怖进行测试,但我绝对同意摆脱这些游标(以及 Schlemiel-the-Painter 字符串连接) ,这是一种很好的方法。 +1。
  • @Aaronaught - 它应该与解密工作正常(我有一些巨大的相关 FOR XML 在 SQL Server 2005 中表现非常好) - 但我想给 OP 一个运行示例而不是非- 基于他的代码的可测试示例。
【解决方案2】:

对于超级用户组(DBA)来说,这可能是一个更好的问题

【讨论】:

  • 我也会把它贴在那里,但我相信 SO 是最好的地方。
  • DBA 肯定是 ServerFault。
【解决方案3】:

考虑到信用卡号码的哈希值非常好 - Visa / MasterCard 16 位 CC 中的最后一位是校验和值。您是否考虑过滚动您自己的并行性,例如,通过让每个线程获取 modulo(4) = thread_id 的那些 CC 数字?假设有 n 个 CPU/核心/无论他们今天如何称呼它们,您都不需要超过 4 个(2*核心)并行处理线程。

【讨论】:

  • 他并没有要求一种通用的方法来并行化任务,他要求的是在 SQL Server 中执行此操作的特定方法,您实际上无法创建“线程”。这根本无法回答问题。
  • 难道四个不同的会话/作业/进程都执行相同的存储过程,每个执行不同的“线程”参数以并行化工作负载吗?另外,我也想在这里学习。我怀疑最好的解决方案是隐藏游标,但我专门在寻找并行解决方案。
【解决方案4】:

是 - 将游标重写为基于集合的查询,SQL Server 优化器应根据基础数据的大小自动并行化(或不并行化)。使 SQL Server 使用并行性不需要“特殊”的开发工作,除了一些基本的最佳实践,如避免游标。它会自动决定是否可以在多个 proc 上使用并行线程,以及这样做是否有用,然后它可以在运行时为您拆分工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 2020-02-20
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    相关资源
    最近更新 更多