我有一個存儲過程截斷一個不是很大的表(2M記錄,但將來會變大),然後重新填充它。示例版本如下所示:截斷表不釋放LCK_M_SCH_S
ALTER PROCEDURE [SC].[A_SP]
AS
BEGIN
BEGIN TRANSACTION;
BEGIN TRY
TRUNCATE TABLE SC.A_TABLE
IF OBJECT_ID('tempdb..#Trans') IS NOT NULL DROP TABLE #Trans
SELECT
*
INTO
#Trans
FROM
(
SELECT
...
FROM
B_TABLE trans (NOLOCK)
INNER JOIN
... (NOLOCK) ON ...
LEFT OUTER JOIN
... (NOLOCK) ON ...
...
) AS x
INSERT INTO
SC.A_TABLE
(
...
)
SELECT
...
FROM
#Trans (NOLOCK)
DROP TABLE #Trans
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
THROW
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
END
此過程需要幾個小時才能工作。有時候我想借此COUNT
看到用多少完成:
SELECT COUNT(*) FROM A_TABLE (NOLOCK)
這並不返回任何東西(甚至NOLOCK
),因爲LCK_M_SCH_S
鎖在桌子上,因爲TRUNCATE
聲明。我什至不能這樣做:
SELECT object_id('SC.A_TABLE')
另一個有趣的事情是;我有時會通過SSMS停止執行該程序,甚至在此之後我不能採取COUNT
或選擇object_id
。執行似乎suspended
在sys.sysprocesses
,我必須關閉查詢窗口,使其釋放鎖。我懷疑這是因爲我使用交易,並通過停止執行將其置於中間狀態,但我不確定。
我知道截斷表不會花費太多時間,因爲表沒有任何外鍵或索引。
可能是什麼問題?我可以用DELETE
代替這個,但我知道TRUNCATE
在這裏會快很多。
編輯:的DELETE
代替TRUNCATE
工作沒有任何問題,順便說一句,但我只是想用它作爲最後的手段。
好奇的是,你正在使用截斷速度(因爲它沒有記錄),但你把它放在一個事務中......是不是讓它記錄下來?你是否需要在這裏進行交易,因爲你經常消除桌面並可以輕鬆替換它?你可以使用SSIS,它的批量加載比INSERT INTO(兩次)要快。 – JiggsJedi
有趣的是,它似乎在一個事務日誌中截斷一個頁面取消分配而不是刪除... https://stackoverflow.com/questions/1522931/truncate-table-within-transaction – JiggsJedi
@JiggsJedi確切地說,這個過程被稱爲通過另一個程序,而另一個程序則從另一個程序中調用,這是事務性的端對端。 – sotn