超碰人人人人人,亚洲AV午夜福利精品一区二区,亚洲欧美综合区丁香五月1区,日韩欧美亚洲系列

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

使用 TABLOCK 提升 SQL Server 大規(guī)模插入性能

admin
2025年5月7日 22:59 本文熱度 182

當(dāng)我們在 SQL Server 中處理大規(guī)模數(shù)據(jù)插入(INSERT)操作時(shí),往往會因?yàn)橛涗浟魁嫶?、日志寫入多、并發(fā)競爭等原因?qū)е滦阅芟陆怠?/span>TABLOCK 提示(Hint)是 SQL Server 提供的一種有效方式,可以通過減少日志記錄和允許并行加載來提升插入性能。下面,我們就來詳細(xì)討論它的原理、優(yōu)勢及使用方式,并給出一個(gè)類似的示例供參考。

什么是 TABLOCK Hint

在執(zhí)行 INSERT、UPDATE 或 DELETE 等操作時(shí),TABLOCK 會在目標(biāo)表上獲取 表級鎖,并對其施加一段時(shí)間的 模式修復(fù)鎖 (Sch-M)。這意味著在整個(gè)操作執(zhí)行期間,其他事務(wù)無法修改該表的架構(gòu)或進(jìn)行并發(fā)寫入。雖然聽起來會犧牲一定的并發(fā)能力,但對于一次性地批量導(dǎo)入或更新大量數(shù)據(jù)的場景,該鎖策略可以激活更多的優(yōu)化:

  • 最小日志記錄
    可以顯著減少日志寫入量,尤其在批量插入時(shí)不再逐行寫入日志,而是采用批量式記錄的方式。
  • 并行化
    在表被完全鎖定后,SQL Server 可以嘗試使用多個(gè)線程并行插入數(shù)據(jù),從而縮短整體執(zhí)行時(shí)間。

使用場景

一般來說,TABLOCK 適合以下場景:

  • 需要一次性插入大量數(shù)據(jù),并且頻繁的小批次插入不多。
  • 能夠接受在插入過程中暫時(shí)鎖定目標(biāo)表(如批處理或離線數(shù)據(jù)導(dǎo)入)。
  • 提高性能速度比表可用性更加重要的批量場景,例如 ETL 流程、數(shù)據(jù)倉庫加載 或者 大規(guī)模臨時(shí)表作業(yè)
  • 需要利用 SQL Server 并行處理能力,盡快完成數(shù)據(jù)插入。

示例:在 AdventureWorks2022 中使用 TABLOCK

以下示例展示了如何在插入數(shù)據(jù)時(shí)應(yīng)用 TABLOCK,并與不使用 TABLOCK 的情況進(jìn)行對比。假設(shè)我們有一張目標(biāo)表 Sales.SalesOrderDetailBulk 用來存儲大量明細(xì)數(shù)據(jù),源表為 Sales.SalesOrderDetail。

創(chuàng)建或清理目標(biāo)表

-- 如果存在測試表,先刪除  
IF OBJECT_ID('SalesOrderDetailTest', 'U') IS NOT NULL  
    DROPTABLE Sales.SalesOrderDetailTest;  
GO  

-- 創(chuàng)建測試表,模仿原始表結(jié)構(gòu)  
CREATETABLE SalesOrderDetailTest  
(  
    SalesOrderID INTNOTNULL,  
    SalesOrderDetailID INTIDENTITY(1,1) PRIMARY KEY,  
    CarrierTrackingNumber NVARCHAR(25NULL,  
    OrderQty SMALLINTNOTNULL,  
    ProductID INTNOTNULL,  
    SpecialOfferID INTNOTNULL,  
    UnitPrice MONEY NOTNULL,  
    UnitPriceDiscount MONEY NOTNULL,  
    LineTotal AS (OrderQty * UnitPrice * (1 - UnitPriceDiscount)) PERSISTED,  
);  
GO  

-- 批量插入測試數(shù)據(jù)的存儲過程  
CREATEORALTERPROCEDURE GenerateSalesOrderDetailTestData  
    @NumberOfRecords INT = 100000
AS
BEGIN
    SET NOCOUNT ON;  

    -- 使用公共表表達(dá)式(CTE)生成測試數(shù)據(jù)  
    ;WITH NumberedRows AS (  
        SELECT TOP (@NumberOfRecords)  
            ROW_NUMBER() OVER (ORDERBY (SELECTNULL)) ASRowNum
        FROM sys.objects o1  
        CROSSJOIN sys.objects o2  
    )  
    INSERTINTO SalesOrderDetailTest  
    (  
        SalesOrderID,  
        CarrierTrackingNumber,  
        OrderQty,  
        ProductID,  
        SpecialOfferID,  
        UnitPrice,  
        UnitPriceDiscount  
    )  
    SELECT   
        -- 隨機(jī)生成 SalesOrderID  
        ABS(CHECKSUM(NEWID()) % 50000) + 1AS SalesOrderID,  

        -- 隨機(jī)生成跟蹤號  
        'TRK' + RIGHT('00000' + CAST(ABS(CHECKSUM(NEWID()) % 99999ASVARCHAR(5)), 5AS CarrierTrackingNumber,  

        -- 隨機(jī)訂單數(shù)量  
        ABS(CHECKSUM(NEWID()) % 10) + 1AS OrderQty,  

        -- 隨機(jī)產(chǎn)品ID(假設(shè)產(chǎn)品ID范圍)  
        ABS(CHECKSUM(NEWID()) % 1000) + 1AS ProductID,  

        -- 隨機(jī)特殊優(yōu)惠ID  
        ABS(CHECKSUM(NEWID()) % 10) + 1AS SpecialOfferID,  

        -- 隨機(jī)單價(jià)  
        ROUND(ABS(CHECKSUM(NEWID())) % 1000 + 10.002AS UnitPrice,  

        -- 隨機(jī)折扣  
        ROUND(ABS(CHECKSUM(NEWID())) % 20 / 100.002AS UnitPriceDiscount  
    FROM NumberedRows;  
END
GO

-- 執(zhí)行存儲過程生成測試數(shù)據(jù)  
EXEC GenerateSalesOrderDetailTestData @NumberOfRecords = 500000;  
GO  

-- 創(chuàng)建索引以提高查詢性能  
CREATE NONCLUSTERED INDEX IX_SalesOrderDetailTest_ProductID   
ON SalesOrderDetailTest (ProductID);  

CREATE NONCLUSTERED INDEX IX_SalesOrderDetailTest_SalesOrderID   
ON SalesOrderDetailTest (SalesOrderID);
-- 如果已存在,先刪除后再創(chuàng)建
IF OBJECT_ID('SalesOrderDetailBulk', 'U') IS NOT NULL
    DROPTABLE SalesOrderDetailBulk;
GO

-- 創(chuàng)建一張用于演示的表,結(jié)構(gòu)與 Sales.SalesOrderDetail 相似
CREATETABLE SalesOrderDetailBulk
(
    SalesOrderID       INT,
    SalesOrderDetailID INT,
    CarrierTrackingNumber NVARCHAR(25),
    OrderQty           SMALLINT,
    ProductID          INT,
    UnitPrice          MONEY,
    UnitPriceDiscount  MONEY,
    LineTotal          AS (OrderQty * UnitPrice)
);
GO

不使用 TABLOCK 的插入操作

-- 第一次插入:不使用 TABLOCK
SETSTATISTICSTIMEON;  -- 打開時(shí)間統(tǒng)計(jì)
INSERTINTO SalesOrderDetailBulk
    (SalesOrderID, SalesOrderDetailID, CarrierTrackingNumber, OrderQty,
     ProductID, UnitPrice, UnitPriceDiscount)
SELECT
    SalesOrderID, SalesOrderDetailID, CarrierTrackingNumber, OrderQty,
    ProductID, UnitPrice, UnitPriceDiscount
FROM SalesOrderDetailTest
WHERE SalesOrderID < 50000;  -- 只插入部分?jǐn)?shù)據(jù)用于演示
SETSTATISTICSTIMEOFF;     -- 關(guān)閉時(shí)間統(tǒng)計(jì)

?

觀察執(zhí)行結(jié)果,記錄 CPU 時(shí)間、總持續(xù)時(shí)間(Elapsed Time)。

帶有 TABLOCK 提示的插入

為方便比較,先清空目標(biāo)表,然后使用 TABLOCK 提示:

TRUNCATE TABLE SalesOrderDetailBulk;  -- 清空目標(biāo)表

SETSTATISTICSTIMEON;
INSERTINTO SalesOrderDetailBulk WITH (TABLOCK)
    (SalesOrderID, SalesOrderDetailID, CarrierTrackingNumber, OrderQty,
     ProductID, UnitPrice, UnitPriceDiscount)
SELECT
    SalesOrderID, SalesOrderDetailID, CarrierTrackingNumber, OrderQty,
    ProductID, UnitPrice, UnitPriceDiscount
FROM SalesOrderDetailTest
WHERE SalesOrderID < 50000;
SETSTATISTICSTIMEOFF;

因?yàn)槭褂昧吮砑夋i和最小日志記錄機(jī)制,執(zhí)行時(shí)間往往會顯著縮短,尤其在數(shù)據(jù)量更大的情況下效果更明顯。

性能對比與注意事項(xiàng)

在上面的示例中,通常會出現(xiàn)以下結(jié)論:

  • 不使用 TABLOCK
    可能耗時(shí)更長,SQL Server 需要更多的日志寫入。同樣在并發(fā)場景下,可能有一定鎖沖突,但不會一次性全表鎖定。
  • 使用 TABLOCK
    在批量插入時(shí)速度會明顯加快,但插入期間禁止其他事務(wù)對該表進(jìn)行更新、插入或刪除,直到操作完成。

需要注意以下幾點(diǎn):

  1. 表鎖時(shí)機(jī)
    TABLOCK 會鎖住整個(gè)目標(biāo)表,在多用戶訪問頻繁的線上 OLTP 系統(tǒng)中需慎用。
  2. 日志空間
    雖說最小日志記錄會減少寫入量,但在非常龐大的插入規(guī)模下仍會對事務(wù)日志造成壓力,需確保數(shù)據(jù)庫日志文件有足夠空間。
  3. 并行插入
    SQL Server 版本和數(shù)據(jù)庫兼容級別可能影響并行度,如果想發(fā)揮最大化效果,需確認(rèn)實(shí)例和查詢設(shè)置允許并行執(zhí)行。

總結(jié)

TABLOCK 提示是 SQL Server 為了應(yīng)對大規(guī)模數(shù)據(jù)載入所提供的非常實(shí)用的手段之一。在臨時(shí)表操作、批量數(shù)據(jù)遷移和數(shù)據(jù)倉庫加載等場景中,通過最小化日志寫入開啟并行插入,往往能成倍縮短插入時(shí)間。不過,需要根據(jù)實(shí)際業(yè)務(wù)需求,綜合考慮表鎖定帶來的影響和可接受度,再決定是否使用 TABLOCK。在合適的場景中合理運(yùn)用,可以為整體加載流程帶來顯著的性能提升。


閱讀原文:原文鏈接


該文章在 2025/5/8 9:14:09 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved