다른 시나리오에서 최소 로깅 삽입을 테스트하고 있으며 TABLOCK을 사용하여 클러스터되지 않은 인덱스가있는 힙에 INSERT INTO SELECT를 읽은 것을 SQL Server 2016 +가 최소한으로 기록해야하지만 내 경우에는이 작업을 수행 할 때 전체 로깅. 내 데이터베이스는 단순 복구 모델에 있으며 인덱스와 TABLOCK이없는 힙에 최소한으로 기록 된 삽입을 얻습니다.
테스트하기 위해 Stack Overflow 데이터베이스의 오래된 백업을 사용하고 있으며 다음 스키마를 사용하여 Posts 테이블의 복제본을 만들었습니다.
CREATE TABLE [dbo].[PostsDestination](
[Id] [int] NOT NULL,
[AcceptedAnswerId] [int] NULL,
[AnswerCount] [int] NULL,
[Body] [nvarchar](max) NOT NULL,
[ClosedDate] [datetime] NULL,
[CommentCount] [int] NULL,
[CommunityOwnedDate] [datetime] NULL,
[CreationDate] [datetime] NOT NULL,
[FavoriteCount] [int] NULL,
[LastActivityDate] [datetime] NOT NULL,
[LastEditDate] [datetime] NULL,
[LastEditorDisplayName] [nvarchar](40) NULL,
[LastEditorUserId] [int] NULL,
[OwnerUserId] [int] NULL,
[ParentId] [int] NULL,
[PostTypeId] [int] NOT NULL,
[Score] [int] NOT NULL,
[Tags] [nvarchar](150) NULL,
[Title] [nvarchar](250) NULL,
[ViewCount] [int] NOT NULL
)
CREATE NONCLUSTERED INDEX ndx_PostsDestination_Id ON PostsDestination(Id)
그런 다음 posts 테이블을이 테이블에 복사하려고합니다 ...
INSERT INTO PostsDestination WITH(TABLOCK)
SELECT * FROM Posts ORDER BY Id
fn_dblog와 로그 파일 사용법을 보면 최소한의 로깅을 얻지 못한다는 것을 알 수 있습니다. 2016 이전의 버전에서는 인덱스 테이블에 최소한의 로그를 기록하기 위해 추적 플래그 610이 필요하다는 것을 읽었습니다.이 설정도 시도했지만 여전히 기쁨은 없습니다.
여기에 뭔가 빠진 것 같아요?
편집-추가 정보
더 많은 정보를 추가하기 위해 최소 로깅을 감지하기 위해 작성한 다음 절차를 사용하고 있습니다. 아마 여기에 잘못된 것이 있습니다 ...
/*
Example Usage...
EXEC sp_GetLogUseStats
@Sql = '
INSERT INTO PostsDestination
SELECT TOP 500000 * FROM Posts ORDER BY Id ',
@Schema = 'dbo',
@Table = 'PostsDestination',
@ClearData = 1
*/
CREATE PROCEDURE [dbo].[sp_GetLogUseStats]
(
@Sql NVARCHAR(400),
@Schema NVARCHAR(20),
@Table NVARCHAR(200),
@ClearData BIT = 0
)
AS
IF @ClearData = 1
BEGIN
TRUNCATE TABLE PostsDestination
END
/*Checkpoint to clear log (Assuming Simple/Bulk Recovery Model*/
CHECKPOINT
/*Snapshot of logsize before query*/
CREATE TABLE #BeforeLogUsed(
[Db] NVARCHAR(100),
LogSize NVARCHAR(30),
Used NVARCHAR(50),
Status INT
)
INSERT INTO #BeforeLogUsed
EXEC('DBCC SQLPERF(logspace)')
/*Run Query*/
EXECUTE sp_executesql @SQL
/*Snapshot of logsize after query*/
CREATE TABLE #AfterLLogUsed(
[Db] NVARCHAR(100),
LogSize NVARCHAR(30),
Used NVARCHAR(50),
Status INT
)
INSERT INTO #AfterLLogUsed
EXEC('DBCC SQLPERF(logspace)')
/*Return before and after log size*/
SELECT
CAST(#AfterLLogUsed.Used AS DECIMAL(12,4)) - CAST(#BeforeLogUsed.Used AS DECIMAL(12,4)) AS LogSpaceUsersByInsert
FROM
#BeforeLogUsed
LEFT JOIN #AfterLLogUsed ON #AfterLLogUsed.Db = #BeforeLogUsed.Db
WHERE
#BeforeLogUsed.Db = DB_NAME()
/*Get list of affected indexes from insert query*/
SELECT
@Schema + '.' + so.name + '.' + si.name AS IndexName
INTO
#IndexNames
FROM
sys.indexes si
JOIN sys.objects so ON si.[object_id] = so.[object_id]
WHERE
si.name IS NOT NULL
AND so.name = @Table
/*Insert Record For Heap*/
INSERT INTO #IndexNames VALUES(@Schema + '.' + @Table)
/*Get log recrod sizes for heap and/or any indexes*/
SELECT
AllocUnitName,
[operation],
AVG([log record length]) AvgLogLength,
SUM([log record length]) TotalLogLength,
COUNT(*) Count
INTO #LogBreakdown
FROM
fn_dblog(null, null) fn
INNER JOIN #IndexNames ON #IndexNames.IndexName = allocunitname
GROUP BY
[Operation], AllocUnitName
ORDER BY AllocUnitName, operation
SELECT * FROM #LogBreakdown
SELECT AllocUnitName, SUM(TotalLogLength) TotalLogRecordLength
FROM #LogBreakdown
GROUP BY AllocUnitName
다음 코드를 사용하여 색인과 TABLOCK이없는 힙에 삽입하는 중 ...
EXEC sp_GetLogUseStats
@Sql = '
INSERT INTO PostsDestination
SELECT * FROM Posts ORDER BY Id ',
@Schema = 'dbo',
@Table = 'PostsDestination',
@ClearData = 1
나는이 결과를 얻는다
0.0024mb의 로그 파일 증가, 매우 작은 로그 레코드 크기 및 그 중 소수는 이것이 최소한의 로깅을 사용하고 있다는 사실에 만족합니다.
그런 다음 id에 클러스터되지 않은 인덱스를 만들면 ...
CREATE INDEX ndx_PostsDestination_Id ON PostsDestination(Id)
그런 다음 동일한 삽입을 다시 실행하십시오 ...
비 클러스터형 인덱스에서 최소 로깅을 얻지 못했을뿐만 아니라 힙에서도 잃어 버렸습니다. 몇 가지 테스트를 더한 후에 ID 클러스터를 만들면 최소한의 로그는 수행하지만 2016 +를 읽은 것부터 tablock을 사용할 때 클러스터되지 않은 인덱스가있는 힙에 최소한의 로그를 기록해야합니다.
최종 편집 :
SQL Server UserVoice 에서 Microsoft에 동작을보고했으며 응답을 받으면 업데이트됩니다. 또한 https://gavindraper.com/2018/05/29/SQL-Server-Minimal-Logging-Inserts/ 에서 작동 할 수 없었던 최소 로그 시나리오에 대한 자세한 내용을 작성했습니다.