Курсоры, занимающие слишком много времени для 34 миллионов строк и sp выполняются 34 миллиона раз - PullRequest
0 голосов
/ 27 марта 2019

Я использую курсоры для извлечения строк из таблицы, которая содержит 34 миллиона данных, и передачи ее в хранимую процедуру, я имею в виду передачу каждой строки данных, в результате чего вызывается 34 миллиона раз sp, Как избежать курсоров или любых решений

Я знаю, что это длинный код, так как многие просили поставить sp, и я дал sp также

ALTER PROCEDURE [dbo].[UpdateConData]
(
    @UId BIGINT
)
AS
BEGIN
    DECLARE @sTime DATETIME
    DECLARE @eTime DATETIME
    DECLARE @res NVARCHAR(30)
    DECLARE @uId INT
    DECLARE @Email NVARCHAR(256)    
    DECLARE @rCount TINYINT
    DECLARE @sCount TINYINT

    DECLARE conCursor CURSOR FAST_FORWARD LOCAL FOR
        SELECT STime,ETime,res,uId,Email,
            c.RCount,c.SCount FROM PCon c


    OPEN conCursor
    FETCH NEXT FROM conCursor INTO
        @sTime, @eTime, @res, @uId, @Email,
        @rCount, @sCount

    WHILE @@FETCH_STATUS = 0
    BEGIN
        EXEC InsertOrUpdateSCon @sTime, @eTime, @res, @uId, @Email,
            @rCount, @sCount

        UPDATE records
            SET 
                ETime = @eTime
            WHERE PId = @pId AND Type='Sync' and  Integer1 = @uId

        FETCH NEXT FROM conversationCursor INTO
            @sTime, @eTime, @res, @uId, @Email,
            @rCount, @sCount
    END

    CLOSE conCursor
    DEALLOCATE conCursor
END


CREATE PROCEDURE [dbo].[InsertOrUpdateSCon]
(
    @sTime DATETIME,
    @eTime DATETIME,
    @res NVARCHAR(30),
    @uId BIGINT,
    @EmailNVARCHAR(256),
    @rCount TINYINT,
    @sCount TINYINT
)
AS
BEGIN
    DECLARE @conId INT
    DECLARE @dId INT

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

    BEGIN TRANSACTION SCon

    EXEC InsertOrUpdateSDP @sTime, @uId, @Email, @dId OUTPUT

    MERGE Con WITH (HOLDLOCK) a USING
        (SELECT 'Email' AS Type, @res AS Dson, @Email AS MeData,
            @uId AS UId, @sTime AS STime) AS b
        ON a.Type=b.Type AND a.Dson=b.Dson AND a.MeData=b.MeData AND a.UId=b.UId AND a.STime=b.STime
    WHEN MATCHED THEN
        UPDATE SET RCount=RCount + @rCount,
                SCount=SCount + @sCount
    WHEN NOT MATCHED THEN
        INSERT(DId, [Type], Dson, MeData, UId,
            STime, ETime, SCount, RCount)
        VALUES(@dId, b.Type, @res, @Email, @uId,
                @sTime, @eTime, @sCount, @rCount);

    COMMIT TRANSACTION SCon

    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
END



CREATE PROCEDURE [dbo].[InsertOrUpdateSDP ]
(
    @sTime DATETIME,
    @uId BIGINT,
    @Email NVARCHAR(256),
    @dId INT OUTPUT
)
AS
BEGIN


    SELECT TOP 1 @dId = DP.PId FROM DP
        INNER JOIN Email E ON E.PId=DP.PId AND E.Email=@Email
        WHERE PId = 1 /* Email */ AND UId = @dId


    IF @dId IS NULL
    BEGIN
        DECLARE @now DATETIME = GETUTCDATE()


        INSERT INTO tableA ([Type], CTime, LTime, IsActive, IsNotactive)
            VALUES(1, @now, @now, 0, 1)
        SET @dId = SCOPE_IDENTITY()


        INSERT INTO tableB(PId, STime, SSTime, DId, UId, SP)
            VALUES(@dId, @sTime, @stTime, 1, @Id, 1)


        INSERT INTO tableC(PId, Email, DOr, DNS)
            VALUES(@dID, @Email, 0, RIGHT(@Email,
                LEN(@Email) - CHARINDEX('@', @Email)))
    END
    ELSE
    BEGIN
        UPDATE DP SET
            SMTime = @sTime,
            SP = 1
            WHERE PId = @dId AND SMTime < @sTime
    END
END
...