Farklı senaryolarda en az günlük ekleri test ediyorum ve TABLOCK ve SQL Server 2016 + kullanarak kümelenmemiş bir dizin ile bir yığın içine INSERT INTOT okuduğumdan en az günlüğe kaydetmelidir, ancak bu durumda bunu yaparken tam günlük kaydı. Veritabanım basit kurtarma modelindedir ve dizinler ve TABLOCK içermeyen bir yığın üzerinde minimal olarak günlüğe eklenen ekler elde ederim.
Test etmek için yığın taşması veritabanının eski bir yedek kullanıyorum ve aşağıdaki şema ile Gönderiler tablosunun bir kopyası oluşturduk ...
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)
Sonra yazı tablosunu bu tabloya kopyalamaya çalışıyorum ...
INSERT INTO PostsDestination WITH(TABLOCK)
SELECT * FROM Posts ORDER BY Id
Fn_dblog ve günlük dosyası kullanımına baktığımda bundan en az günlük kaydı alamadım. 2016'dan önceki sürümlerin dizinli tablolara minimal olarak giriş yapmak için izleme bayrağı 610 gerektirdiğini okudum, bunu da ayarlamayı denedim ama yine de hiç neşe yok.
Sanırım burada bir şey eksik mi?
DÜZENLE - Daha Fazla Bilgi
Daha fazla bilgi eklemek için, en az günlük kaydı algılamaya çalışmak üzere yazdığım aşağıdaki yordamı kullanıyorum, belki burada yanlış bir şey var ...
/*
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
Aşağıdaki kodu kullanarak dizin ve TABLOCK içermeyen bir yığına ekleme ...
EXEC sp_GetLogUseStats
@Sql = '
INSERT INTO PostsDestination
SELECT * FROM Posts ORDER BY Id ',
@Schema = 'dbo',
@Table = 'PostsDestination',
@ClearData = 1
Bu sonuçları alıyorum
0.0024mb günlük dosyası büyüme, çok küçük günlük kayıt boyutları ve bunların çok azı, bu minimum günlük kaydı kullanmak mutluyum.
Sonra id üzerinde kümelenmemiş bir dizin oluşturmak ...
CREATE INDEX ndx_PostsDestination_Id ON PostsDestination(Id)
Sonra aynı ek parçamı tekrar çalıştır ...
Sadece kümelenmemiş dizinde en az günlük kaydı almak değil, aynı zamanda yığın üzerinde kaybettim. Biraz daha fazla test yaptıktan sonra, kimlik kümelenmiş olsaydı en az günlüğe yazıyor ancak 2016 + 'dan okuduğumdan tablock kullanıldığında kümelenmemiş dizinle bir yığın için minimal olarak oturum açmalıdır.
NİHAİ DÜZENLEME :
Davranışı SQL Server UserVoice üzerinde Microsoft'a bildirdim ve bir yanıt alırsam güncelleştirilir. Ayrıca https://gavindraper.com/2018/05/29/SQL-Server-Minimal-Logging-Inserts/ adresinde çalışamayacağım minimal günlük senaryolarının tüm ayrıntılarını yazdım.