SQL Server批量性能优化

问题描述 投票:0回答:1

我们有以下架构

  • 暂存台
  • 读表

临时表是从外部数据库直接加载的,每周一次,临时表中的数据会加载到读取表中,并有一些内部联接,以减少用户点击读取表时的读取次数。问题是临时表中的数据量足够大,以至于超出了我们的数据库日志,因此我们被要求实施批处理。

我有下面的脚本,它可以工作,但到目前为止它只运行我们需要迁移的数据的 1/8,并且运行大约需要 4 小时。暂存表中的记录量约为 8000 万条记录,表 2 约为 400 条记录(带索引、唯一值和应用的 PK)。

DECLARE @PageSize int = 50000;
DECLARE @PageIndex int = 0;
DECLARE @TotalPages int = 0;


SELECT @TotalPages = ((count(1) / @PageSize) + 1)
FROM Table1_Staging t1
INNER JOIN Table2 t2 ON t2.r1 = t1.r7
INNER JOIN Table2 t3 ON t3.r1 = t1.r8

SELECT @TotalPages;

WHILE (@PageIndex <= @TotalPages)
BEGIN
    BEGIN TRANSACTION
        INSERT INTO Table1 ( [row1], [row2], [row3], [row4],
                              [row5], [row6], [row7], [row8])
        SELECT  t1.r2,
                t1.r3,
                t2.r1,
                t2.r3,
                t3.r3,
                t1.r6,
                IIF(TRY_CONVERT(datetime, t1.DATE) IS NULL,
                    DATEADD(YEAR, -1, GETDATE()),
                    TRY_CONVERT(datetime, t1.DATE))
                    AS date,
                t1.r1
        FROM Table1_Staging t1
                    INNER JOIN Table2 t2 ON t2.r1 = t1.r7
                    INNER JOIN Table2 t3 ON t3.r1 = t1.r8
        ORDER BY t1.r2 DESC
        OFFSET (@PageSize * @PageIndex) ROWS
        FETCH NEXT @PageSize ROWS ONLY;

    COMMIT TRANSACTION;

    /** Increments the Page Size */
    SET @PageIndex  = @PageIndex  + 1;
END

有人对优化此查询或仅在 SQL 中批量加载数据的不同方式有任何建议吗?应用于所有表的索引和 PK 已针对查询进行了优化。或者我应该将 PageSize 增加到像 500,000 这样的大值。

sql sql-server batch-processing
1个回答
1
投票

我们最终进行的优化如下: 在临时表上添加 IDENTITY INT 主键,删除行号分页并使用 KEYSET 分页。将 4 小时的查询缩短至约 22 分钟。

DECLARE @PageSizeCurrent int = 0;
DECLARE @PageSizeIncrement int = 50000;
DECLARE @rowCount int = 1;

WHILE (@rowCount > 0)
BEGIN
BEGIN TRANSACTION
    INSERT INTO Table1 ([row1], [row2], [row3], [row4],
                        [row5], [row6], [row7], [row8])
        SELECT  
            t1.r2, t1.r3, t2.r1, t2.r3,
            t3.r3, t1.r6, 
            IIF(TRY_CONVERT(datetime, t1.DATE) IS NULL, DATEADD(YEAR, -1, 
                 GETDATE()),
            TRY_CONVERT(datetime, t1.DATE)) AS date,
            t1.r1
        FROM 
            Table1_Staging t1
        INNER JOIN 
            Table2 t2 ON t2.r1 = t1.r7
        INNER JOIN 
            Table2 t3 ON t3.r1 = t1.r8
    WHERE t1.[id] > @PageSize AND t1.[id] < (@PageSize + @PageSizeIncrement)

    SET @rowCount = @@ROWCOUNT


    COMMIT TRANSACTION;

    /** Increments the Page Size */
    SET @PageSize = @PageSize + @PageSizeIncrement;
END
© www.soinside.com 2019 - 2024. All rights reserved.