あまりにも大きなテーブル(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
で)何も返さないテーブルためのTRUNCATE
ステートメントのLCK_M_SCH_S
ロックがあるため。私もすることはできません:
SELECT object_id('SC.A_TABLE')
他の興味深いものがあります。私はときどきSSMSを介して手順の実行を停止し、その後も私はCOUNT
を取ることができませんまたはobject_id
を選択します。実行はでsys.sysprocesses
と思われ、ロックを解除するためにクエリウィンドウを閉じる必要があります。私はトランザクションを使用し、実行を中止して中間状態にしておくので、それは疑わしいですが、わかりません。
テーブルを切り詰めるには、テーブルに外部キーやインデックスがないため、時間がかかりません。
何が問題なのですか?私はこれの代わりにDELETE
を使うかもしれませんが、私はTRUNCATE
がはるかに速いことを知っています。
EDIT:問題なくDELETE
代わりのTRUNCATE
作品ところで、私は最後の手段としてのみ、それを使用したいです。
奇妙なことに、スピード(ログに記録されていない)のためにトランケートを使用していますが、トランザクションに入れています...ログに記録されませんか?あなたは日常的にテーブルを削除しており、簡単にそれを置き換えることができるので、ここでトランザクションが必要ですか?代わりにSSISを使用できますか。その一括読み込みはINSERT INTO(2回)より高速です。 – JiggsJedi
興味深いことに、トランザクションのトランケートは、削除の代わりにページの割り当て解除を記録するようです... https://stackoverflow.com/questions/1522931/truncate-table-within-transaction – JiggsJedi
@JiggsJediまさにこの手順は、別のプロシージャによって呼び出され、別のプロシージャから呼び出され、トランザクションの終わりから終わりまでの間に終了します。 – sotn