代码之家  ›  专栏  ›  技术社区  ›  Russ

我可以在多个CPU上分布一个长时间运行的存储过程吗?

  •  4
  • Russ  · 技术社区  · 15 年前

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

    我在SQL Server的gets中有一个存储过程,并对一块数据进行解密。(这种情况下是信用卡。)

    大多数情况下,性能是可以接受的,但是有几个客户的流程非常缓慢,实际需要1分钟才能完成。(准确地说,从SQL Server返回59377ms,但根据负载的不同,可能会有几百ms的变化)

    当我观察这个过程时,我看到SQL只使用一个过程来执行整个过程,而且通常只使用过程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
    
    4 回复  |  直到 15 年前
        1
  •  1
  •   Cade Roux    15 年前

    使用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
    
        2
  •  0
  •   Cody C    15 年前

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

        3
  •  0
  •   Adam Musch    15 年前

    考虑到信用卡号码散列得很好——Visa/MasterCard 16位CC中的最后一位是校验和值。例如,您是否考虑通过让每个线程获取modulo(4)=thread_u id的CC编号来滚动自己的并行性?假设有N个CPU/内核/不管他们今天怎么称呼它们,您不需要超过4(2*核)的并行处理线程。

        4
  •  0
  •   onupdatecascade    15 年前

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