AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 203063
Accepted
Josh Darnell
Josh Darnell
Asked: 2018-04-05 11:49:25 +0800 CST2018-04-05 11:49:25 +0800 CST 2018-04-05 11:49:25 +0800 CST

Por que CHECKDB está lendo o arquivo de log de transações em um banco de dados com uma tabela com otimização de memória?

  • 772

tl; dr : por que CHECKDB está lendo o log de transações para um banco de dados de usuário com tabelas otimizadas para memória?


Parece que CHECKDB está lendo o arquivo de log de transações do banco de dados do usuário quando está verificando um dos meus bancos de dados - em particular, um banco de dados que usa tabelas OLTP na memória.

CHECKDB para este banco de dados ainda termina em um período de tempo razoável, então estou apenas curioso sobre o comportamento; mas é definitivamente a duração mais longa para CHECKDB de todos os bancos de dados nesta instância.

Ao examinar o épico " CHECKDB From Every Angle: Complete description of all CHECKDB stage " de Paul Randal ", vejo que o CHECKDB pré-SQL 2005 costumava ler o log para obter uma visão consistente do banco de dados. Mas como é 2016, ele usa um instantâneo de banco de dados interno.

No entanto, um dos pré- requisitos para instantâneos é que:

O banco de dados de origem não deve conter um grupo de arquivos MEMORY_OPTIMIZED_DATA

Meu banco de dados de usuário tem um desses grupos de arquivos, então parece que os instantâneos estão fora da mesa.

De acordo com os documentos CHECKDB :

Se um instantâneo não puder ser criado ou TABLOCK for especificado, DBCC CHECKDB adquirirá bloqueios para obter a consistência necessária. Nesse caso, um bloqueio de banco de dados exclusivo é necessário para realizar as verificações de alocação e os bloqueios de tabela compartilhada são necessários para realizar as verificações de tabela.

Ok, então estamos fazendo o bloqueio de banco de dados e tabela em vez de instantâneos. Mas isso ainda não explica por que ele precisa ler o log de transações. Então o que dá?

Forneci um script abaixo para reproduzir o cenário. Ele é usado sys.dm_io_virtual_file_statspara identificar as leituras do arquivo de log.

Observe que na maioria das vezes ele lê uma pequena parte do log (480 KB), mas ocasionalmente lê muito mais (48,2 MB). No meu cenário de produção, ele lê a maior parte do arquivo de log (~1,3 GB do arquivo de 2 GB) todas as noites à meia-noite quando executamos CHECKDB.

Aqui está um exemplo das saídas que obtive até agora com o script:

collection_time            num_of_reads     num_of_bytes_read
2018-04-04 15:12:29.203    106              50545664

Ou isto:

collection_time            num_of_reads     num_of_bytes_read
2018-04-04 15:25:14.227    1                491520

Se eu substituir os objetos com otimização de memória por tabelas regulares, a saída será assim:

collection_time            num_of_reads     num_of_bytes_read
2018-04-04 15:21:03.207    0                0

Por que CHECKDB está lendo o arquivo de log? E especialmente, por que ocasionalmente lê uma parte muito maior do arquivo de log?

Aqui está o script real:

-- let's have a fresh DB
USE [master];

IF (DB_ID(N'LogFileRead_Test') IS NOT NULL) 
BEGIN
    ALTER DATABASE [LogFileRead_Test]
    SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE [LogFileRead_Test];
END

GO
CREATE DATABASE [LogFileRead_Test]

GO
ALTER DATABASE [LogFileRead_Test]
MODIFY FILE
(
    NAME = LogFileRead_Test_log,
    SIZE = 128MB
);

-- Hekaton-yeah, I want memory optimized data
GO
ALTER DATABASE [LogFileRead_Test]
ADD FILEGROUP [LatencyTestInMemoryFileGroup] CONTAINS MEMORY_OPTIMIZED_DATA;

GO
ALTER DATABASE [LogFileRead_Test]
ADD FILE 
(
    NAME = [LatencyTestInMemoryFile], 
    FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\LogFileRead_Test_SessionStateInMemoryFile'
) TO FILEGROUP [LatencyTestInMemoryFileGroup];

GO
USE [LogFileRead_Test]

GO
CREATE TYPE [dbo].[InMemoryIdTable] AS TABLE (
    [InMemoryId] NVARCHAR (88) COLLATE Latin1_General_100_BIN2 NOT NULL,
    PRIMARY KEY NONCLUSTERED HASH ([InMemoryId]) WITH (BUCKET_COUNT = 240))
    WITH (MEMORY_OPTIMIZED = ON);

GO
CREATE TABLE [dbo].[InMemoryStuff] (
    [InMemoryId]   NVARCHAR (88)    COLLATE Latin1_General_100_BIN2 NOT NULL,
    [Created]     DATETIME2 (7)    NOT NULL,
    CONSTRAINT [PK_InMemoryStuff_InMemoryId] PRIMARY KEY NONCLUSTERED HASH ([InMemoryId]) WITH (BUCKET_COUNT = 240)
)
WITH (MEMORY_OPTIMIZED = ON);

GO
-- RBAR is the new black (we need some logs to read)
declare @j int = 0;
while @j < 100000
begin
    INSERT INTO [dbo].[InMemoryStuff](InMemoryId, Created) VALUES ('Description' + CAST(@j as varchar), GETDATE());
    set @j = @j + 1;
end

-- grab a baseline of virtual file stats to be diff'd later
select f.num_of_reads, f.num_of_bytes_read
into #dm_io_virtual_file_stats
from sys.dm_io_virtual_file_stats(default, default) f
where database_id = db_id('LogFileRead_Test') and file_id = FILE_IDEX('LogFileRead_Test_log');

-- hands off my log file, CHECKDB!
GO
DBCC CHECKDB ([LogFileRead_Test]) WITH NO_INFOMSGS, ALL_ERRORMSGS, DATA_PURITY;

-- grab the latest virtual file stats, and compare with the previous capture
GO
select f.num_of_reads, f.num_of_bytes_read
into #checkdb_stats
from sys.dm_io_virtual_file_stats(default, default) f
where database_id = db_id('LogFileRead_Test') and file_id = FILE_IDEX('LogFileRead_Test_log');

select 
        collection_time = GETDATE() 
        , num_of_reads = - f.num_of_reads + t.num_of_reads
        , num_of_bytes_read = - f.num_of_bytes_read + t.num_of_bytes_read
into #dm_io_virtual_file_stats_diff
from #dm_io_virtual_file_stats f, #checkdb_stats t;

drop table #checkdb_stats;
drop table #dm_io_virtual_file_stats;

-- CHECKDB ignored my comment
select collection_time, num_of_reads, num_of_bytes_read
from #dm_io_virtual_file_stats_diff d
order by d.collection_time;

drop table #dm_io_virtual_file_stats_diff;

-- I was *not* raised in a barn
USE [master];

ALTER DATABASE [LogFileRead_Test]
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [LogFileRead_Test];

Como esse repro geralmente gera apenas 1 ou 106 leituras de arquivos de log, pensei em pesquisar o 1 com uma sessão de eventos estendidos file_read e file_read_completed.

name                timestamp                   mode        offset  database_id file_id size    duration
file_read           2018-04-06 10:51:11.1098141 Contiguous  72704   9           2       0       NULL    
file_read_completed 2018-04-06 10:51:11.1113345 Contiguous  72704   9           2       491520  1       

E aqui estão os detalhes do VLF ( DBCC LOGINFO()) para o contexto desses deslocamentos e tal:

RecoveryUnitId  FileId  FileSize    StartOffset FSeqNo  Status  Parity  CreateLSN
0               2       2031616     8192        34      2       64      0
0               2       2031616     2039808     35      2       64      0
0               2       2031616     4071424     36      2       64      0
0               2       2285568     6103040     37      2       64      0
0               2       15728640    8388608     38      2       64      34000000005200001
0               2       15728640    24117248    39      2       64      34000000005200001
0               2       15728640    39845888    40      2       64      34000000005200001
0               2       15728640    55574528    0       0       0       34000000005200001
0               2       15728640    71303168    0       0       0       34000000005200001
0               2       15728640    87031808    0       0       0       34000000005200001
0               2       15728640    102760448   0       0       0       34000000005200001
0               2       15728640    118489088   0       0       0       34000000005200001

Então, a operação CHECKDB:

  • começou a ler 63 KB (64.512 bytes) no primeiro VLF,
  • leia 480 KB (491.520 bytes) e
  • não leu os últimos 1.441 KB ( 1.475.584 bytes) do VLF

Também capturei as pilhas de chamadas, caso sejam úteis.

pilha de chamadas file_read:

(00007ffd`999a0860)   sqlmin!XeSqlPkg::file_read::Publish+0x1dc   |  (00007ffd`999a0b40)   sqlmin!XeSqlPkg::file_read_enqueued::Publish
(00007ffd`9a825e30)   sqlmin!FireReadEvent+0x118   |  (00007ffd`9a825f60)   sqlmin!FireReadEnqueuedEvent
(00007ffd`9980b500)   sqlmin!FCB::AsyncRead+0x74d   |  (00007ffd`9980b800)   sqlmin!FCB::AsyncReadInternal
(00007ffd`9970e9d0)   sqlmin!SQLServerLogMgr::LogBlockReadAheadAsync+0x6a6   |  (00007ffd`9970ec00)   sqlmin!LBH::Destuff
(00007ffd`9970a6d0)   sqlmin!LogConsumer::GetNextLogBlock+0x1591   |  (00007ffd`9970ab70)   sqlmin!LogPoolPrivateCacheBufferMgr::Lookup
(00007ffd`9a9fcbd0)   sqlmin!SQLServerLogIterForward::GetNext+0x258   |  (00007ffd`9a9fd2d0)   sqlmin!SQLServerLogIterForward::GetNextBlock
(00007ffd`9aa417f0)   sqlmin!SQLServerCOWLogIterForward::GetNext+0x2b   |  (00007ffd`9aa418c0)   sqlmin!SQLServerCOWLogIterForward::StartScan
(00007ffd`9aa64210)   sqlmin!RecoveryMgr::AnalysisPass+0x83b   |  (00007ffd`9aa65100)   sqlmin!RecoveryMgr::AnalyzeLogRecord
(00007ffd`9aa5ed50)   sqlmin!RecoveryMgr::PhysicalRedo+0x233   |  (00007ffd`9aa5f790)   sqlmin!RecoveryMgr::PhysicalCompletion
(00007ffd`9aa7fd90)   sqlmin!RecoveryUnit::PhysicalRecovery+0x358   |  (00007ffd`9aa802c0)   sqlmin!RecoveryUnit::CompletePhysical
(00007ffd`9a538b90)   sqlmin!StartupCoordinator::NotifyPhaseStart+0x3a   |  (00007ffd`9a538bf0)   sqlmin!StartupCoordinator::NotifyPhaseEnd
(00007ffd`9a80c430)   sqlmin!DBTABLE::ReplicaCreateStartup+0x2f4   |  (00007ffd`9a80c820)   sqlmin!DBTABLE::RefreshPostRecovery
(00007ffd`9a7ed0b0)   sqlmin!DBMgr::SyncAndLinkReplicaRecoveryPhase+0x890   |  (00007ffd`9a7edff0)   sqlmin!DBMgr::DetachDB
(00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica+0x869   |  (00007ffd`9a7f3630)   sqlmin!DBMgr::StrandTransientReplica
(00007ffd`9a7f2ae0)   sqlmin!DBMgr::CreateTransientReplica+0x118   |  (00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica
(00007ffd`99ec6d30)   sqlmin!DBDDLAgent::CreateReplica+0x1b5   |  (00007ffd`99ec6f90)   sqlmin!FSystemDatabase
(00007ffd`9abaaeb0)   sqlmin!UtilDbccCreateReplica+0x82   |  (00007ffd`9abab000)   sqlmin!UtilDbccDestroyReplica
(00007ffd`9ab0d7e0)   sqlmin!UtilDbccCheckDatabase+0x994   |  (00007ffd`9ab0ffd0)   sqlmin!UtilDbccRetainReplica
(00007ffd`9ab0cfc0)   sqlmin!DbccCheckDB+0x22d   |  (00007ffd`9ab0d380)   sqlmin!DbccCheckFilegroup
(00007ffd`777379c0)   sqllang!DbccCommand::Execute+0x193   |  (00007ffd`77737d70)   sqllang!DbccHelp
(00007ffd`777e58d0)   sqllang!CStmtDbcc::XretExecute+0x889   |  (00007ffd`777e6250)   sqllang!UtilDbccSetPermissionFailure
(00007ffd`76b02eb0)   sqllang!CMsqlExecContext::ExecuteStmts<1,1>+0x40d   |  (00007ffd`76b03410)   sqllang!CSQLSource::CleanupCompileXactState
(00007ffd`76b03a60)   sqllang!CMsqlExecContext::FExecute+0xa9e   |  (00007ffd`76b043d0)   sqllang!CCacheObject::Release
(00007ffd`76b03430)   sqllang!CSQLSource::Execute+0x981   |  (00007ffd`76b039b0)   sqllang!CSQLLock::Cleanup

pilha de chamadas file_read_completed:

(00007ffd`99995cc0)   sqlmin!XeSqlPkg::file_read_completed::Publish+0x1fc   |  (00007ffd`99995fe0)   sqlmin!XeSqlPkg::file_write_completed::Publish
(00007ffd`9a826630)   sqlmin!FireIoCompletionEventLong+0x227   |  (00007ffd`9a8269c0)   sqlmin!IoRequestDispenser::Dump
(00007ffd`9969bee0)   sqlmin!FCB::IoCompletion+0x8e   |  (00007ffd`9969c180)   sqlmin!IoRequestDispenser::Put
(00007ffd`beaa11e0)   sqldk!IOQueue::CheckForIOCompletion+0x426   |  (00007ffd`beaa1240)   sqldk!SystemThread::GetCurrentId
(00007ffd`beaa15b0)   sqldk!SOS_Scheduler::SwitchContext+0x173   |  (00007ffd`beaa18a0)   sqldk!SOS_Scheduler::Switch
(00007ffd`beaa1d00)   sqldk!SOS_Scheduler::SuspendNonPreemptive+0xd3   |  (00007ffd`beaa1db0)   sqldk!SOS_Scheduler::ResumeNoCuzz
(00007ffd`99641720)   sqlmin!EventInternal<SuspendQueueSLock>::Wait+0x1e7   |  (00007ffd`99641ae0)   sqlmin!SOS_DispatcherPool<DispatcherWorkItem,DispatcherWorkItem,SOS_DispatcherQueue<DispatcherWorkItem,0,DispatcherWorkItem>,DispatcherPoolConfig,void * __ptr64>::GetDispatchers
(00007ffd`9aa437c0)   sqlmin!SQLServerLogMgr::CheckLogBlockReadComplete+0x1e6   |  (00007ffd`9aa44670)   sqlmin!SQLServerLogMgr::ValidateBlock
(00007ffd`9970a6d0)   sqlmin!LogConsumer::GetNextLogBlock+0x1b37   |  (00007ffd`9970ab70)   sqlmin!LogPoolPrivateCacheBufferMgr::Lookup
(00007ffd`9a9fcbd0)   sqlmin!SQLServerLogIterForward::GetNext+0x258   |  (00007ffd`9a9fd2d0)   sqlmin!SQLServerLogIterForward::GetNextBlock
(00007ffd`9aa417f0)   sqlmin!SQLServerCOWLogIterForward::GetNext+0x2b   |  (00007ffd`9aa418c0)   sqlmin!SQLServerCOWLogIterForward::StartScan
(00007ffd`9aa64210)   sqlmin!RecoveryMgr::AnalysisPass+0x83b   |  (00007ffd`9aa65100)   sqlmin!RecoveryMgr::AnalyzeLogRecord
(00007ffd`9aa5ed50)   sqlmin!RecoveryMgr::PhysicalRedo+0x233   |  (00007ffd`9aa5f790)   sqlmin!RecoveryMgr::PhysicalCompletion
(00007ffd`9aa7fd90)   sqlmin!RecoveryUnit::PhysicalRecovery+0x358   |  (00007ffd`9aa802c0)   sqlmin!RecoveryUnit::CompletePhysical
(00007ffd`9a538b90)   sqlmin!StartupCoordinator::NotifyPhaseStart+0x3a   |  (00007ffd`9a538bf0)   sqlmin!StartupCoordinator::NotifyPhaseEnd
(00007ffd`9a80c430)   sqlmin!DBTABLE::ReplicaCreateStartup+0x2f4   |  (00007ffd`9a80c820)   sqlmin!DBTABLE::RefreshPostRecovery
(00007ffd`9a7ed0b0)   sqlmin!DBMgr::SyncAndLinkReplicaRecoveryPhase+0x890   |  (00007ffd`9a7edff0)   sqlmin!DBMgr::DetachDB
(00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica+0x869   |  (00007ffd`9a7f3630)   sqlmin!DBMgr::StrandTransientReplica
(00007ffd`9a7f2ae0)   sqlmin!DBMgr::CreateTransientReplica+0x118   |  (00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica
(00007ffd`99ec6d30)   sqlmin!DBDDLAgent::CreateReplica+0x1b5   |  (00007ffd`99ec6f90)   sqlmin!FSystemDatabase
(00007ffd`9abaaeb0)   sqlmin!UtilDbccCreateReplica+0x82   |  (00007ffd`9abab000)   sqlmin!UtilDbccDestroyReplica
(00007ffd`9ab0d7e0)   sqlmin!UtilDbccCheckDatabase+0x994   |  (00007ffd`9ab0ffd0)   sqlmin!UtilDbccRetainReplica
(00007ffd`9ab0cfc0)   sqlmin!DbccCheckDB+0x22d   |  (00007ffd`9ab0d380)   sqlmin!DbccCheckFilegroup
(00007ffd`777379c0)   sqllang!DbccCommand::Execute+0x193   |  (00007ffd`77737d70)   sqllang!DbccHelp

Esses rastreamentos de pilha se correlacionam com a resposta de Max, indicando que CHECKDB está usando um instantâneo interno, apesar da presença das tabelas Hekaton.

Eu li que os instantâneos executam a recuperação para desfazer transações não confirmadas :

As transações não confirmadas são revertidas em um instantâneo de banco de dados recém-criado porque o Mecanismo de Banco de Dados executa a recuperação após a criação do instantâneo (as transações no banco de dados não são afetadas).

Mas isso ainda não explica por que uma grande parte do arquivo de log é frequentemente lida no meu cenário de produção (e ocasionalmente na reprodução fornecida aqui). Acho que não tenho tantas transações em voo em um determinado momento no meu aplicativo, e certamente não há nenhuma na reprodução aqui.

sql-server sql-server-2016
  • 1 1 respostas
  • 977 Views

1 respostas

  • Voted
  1. Best Answer
    Hannah Vernon
    2018-04-07T11:17:37+08:002018-04-07T11:17:37+08:00

    Embora a documentação do SQL Server afirme que os bancos de dados com tabelas "na memória" não oferecem suporte a instantâneos, o instantâneo "interno" necessário para DBCC CHECKDBainda pode ser criado, pois a operação checkdb não toca nas tabelas na memória e o instantâneo captura apenas as alterações para as tabelas em disco.

    Presumivelmente, a Microsoft optou por evitar instantâneos criados pelo usuário em bancos de dados com tabelas na memória, pois eles precisariam duplicar as estruturas na memória para que o instantâneo realmente fosse um instantâneo completo do sentido normal, centrado no usuário. A duplicação das tabelas na memória para um instantâneo pode facilmente fazer com que o servidor fique sem memória, o que não é A Good Thing™

    Você pode provar por si mesmo que um instantâneo interno do DBCC está sendo criado observando a pasta de dados onde o arquivo de dados do banco de dados primário reside durante a execução DBCC CHECKDB. Se um instantâneo interno for criado, você verá um arquivo chamado LogFileRead_Test.mdf_MSSQL_DBCC7( 7pode ser diferente - ele representa o ID do banco de dados para seu banco de dados).

    Após a criação do arquivo de instantâneo, é necessário que o SQL Server execute a recuperação no banco de dados para colocá-lo em um estado consistente necessário para a execução do DBCC CHECKDB. Qualquer ação de leitura de log que você está vendo provavelmente é resultado desse processo de recuperação. Eu construí um equipamento rápido para verificar a saída de várias DBCC CHECKDBações, o que prova que, se não houver transações entre checkdbs, não haverá leituras de arquivos de log.

    USE master;
    SET IMPLICIT_TRANSACTIONS OFF;
    USE [master];
    IF (DB_ID(N'LogFileRead_Test') IS NOT NULL) 
    BEGIN
        ALTER DATABASE [LogFileRead_Test]
        SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
        DROP DATABASE [LogFileRead_Test];
    END
    
    CREATE DATABASE [LogFileRead_Test]
    ALTER DATABASE [LogFileRead_Test]
    MODIFY FILE
    (
        NAME = LogFileRead_Test_log,
        SIZE = 128MB
    );
    
    ALTER DATABASE [LogFileRead_Test]
    ADD FILEGROUP [LatencyTestInMemoryFileGroup] CONTAINS MEMORY_OPTIMIZED_DATA;
    ALTER DATABASE [LogFileRead_Test]
    ADD FILE 
    (
        NAME = [LatencyTestInMemoryFile], 
        FILENAME = 'C:\temp\LogFileRead_Test_SessionStateInMemoryFile'
    ) TO FILEGROUP [LatencyTestInMemoryFileGroup];
    GO
    
    USE LogFileRead_Test;
    
    CREATE TABLE [dbo].[InMemoryStuff] (
        [InMemoryId]   NVARCHAR (88)    COLLATE Latin1_General_100_BIN2 NOT NULL,
        [Created]     DATETIME2 (7)    NOT NULL,
        CONSTRAINT [PK_InMemoryStuff_InMemoryId] 
        PRIMARY KEY NONCLUSTERED 
        HASH ([InMemoryId]) WITH (BUCKET_COUNT = 240)
    )
    WITH (MEMORY_OPTIMIZED = ON);
    
    ;WITH src AS (
        SELECT n.Num
        FROM (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))n(Num)
    )
    INSERT INTO [dbo].[InMemoryStuff] (InMemoryId, Created) 
    SELECT 'Description' + CONVERT(varchar(30)
            , ((s1.Num * 10000) 
             + (s2.Num * 1000) 
             + (s3.Num * 100) 
             + (s4.Num * 10) 
             + (s5.Num)))
        , GETDATE()
    FROM src s1
        CROSS JOIN src s2
        CROSS JOIN src s3
        CROSS JOIN src s4
        CROSS JOIN src s5;
    USE master;
    
    DECLARE @cmd nvarchar(max);
    DECLARE @msg nvarchar(1000);
    DECLARE @l int;
    DECLARE @m int;
    SET @m = 10;
    SET @l = 1;
    IF OBJECT_ID(N'tempdb..#vfs', N'U') IS NOT NULL DROP TABLE #vfs;
    CREATE TABLE #vfs (
        vfs_run int NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED
        , collection_time datetime2(7)
        , num_of_reads bigint
        , num_of_bytes_read bigint
    );
    
    WHILE @l <= @m 
    BEGIN
    SET @msg = N'loop ' + CONVERT(nvarchar(10), @l);
    RAISERROR (@msg, 0, 1) WITH NOWAIT;
    
    SET @cmd = 'USE [LogFileRead_Test];
    -- grab a baseline of virtual file stats to be diff''d later
    select f.num_of_reads, f.num_of_bytes_read
    into #dm_io_virtual_file_stats
    from sys.dm_io_virtual_file_stats(default, default) f
    where database_id = db_id(''LogFileRead_Test'') and file_id = FILE_IDEX(''LogFileRead_Test_log'');
    
    DBCC CHECKDB ([LogFileRead_Test]) WITH NO_INFOMSGS, ALL_ERRORMSGS, DATA_PURITY;
    
    -- grab the latest virtual file stats, and compare with the previous capture
    select f.num_of_reads, f.num_of_bytes_read
    into #checkdb_stats
    from sys.dm_io_virtual_file_stats(default, default) f
    where database_id = db_id(''LogFileRead_Test'') and file_id = FILE_IDEX(''LogFileRead_Test_log'');
    
    select 
            collection_time = GETDATE() 
            , num_of_reads = - f.num_of_reads + t.num_of_reads
            , num_of_bytes_read = - f.num_of_bytes_read + t.num_of_bytes_read
    into #dm_io_virtual_file_stats_diff
    from #dm_io_virtual_file_stats f, #checkdb_stats t;
    
    --drop table #checkdb_stats;
    --drop table #dm_io_virtual_file_stats;
    
    -- CHECKDB ignored my comment
    select collection_time, num_of_reads, num_of_bytes_read
    from #dm_io_virtual_file_stats_diff d
    order by d.collection_time;
    
    --drop table #dm_io_virtual_file_stats_diff;
    ';
    INSERT INTO #vfs (collection_time, num_of_reads, num_of_bytes_read)
    EXEC sys.sp_executesql @cmd;
    
    SET @l += 1;
    END
    
    USE master;
    SET @cmd = 'USE [master];
    ALTER DATABASE [LogFileRead_Test]
    SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE [LogFileRead_Test];
    ';
    EXEC sys.sp_executesql @cmd;
    
    SELECT *
    FROM #vfs
    ORDER BY vfs_run;
    

    Os resultados:

    ╔═════════╦═════════════════════════════╦═════════ ═════╦═══════════════════╗
    ║ vfs_run ║ collection_time ║ num_of_reads ║ num_of_bytes_read ║
    ╠═════════╬═════════════════════════════╬═════════ ═════╬═══════════════════╣
    ║ 1 ║ 06-04-2018 15:53:37.6566667 ║ 1 ║ 491520 ║
    ║ 2 ║ 06-04-2018 15:53:37.8300000 ║ 0 ║ 0 ║
    ║ 3 ║ 06-04-2018 15:53:38.0166667 ║ 0 ║ 0 ║
    ║ 4 ║ 06-04-2018 15:53:38.1866667 ║ 0 ║ 0 ║
    ║ 5 ║ 06-04-2018 15:53:38.3766667 ║ 0 ║ 0 ║
    ║ 6 ║ 06-04-2018 15:53:38.5633333 ║ 0 ║ 0 ║
    ║ 7 ║ 06-04-2018 15:53:38.7333333 ║ 0 ║ 0 ║
    ║ 8 ║ 06-04-2018 15:53:38.9066667 ║ 0 ║ 0 ║
    ║ 9 ║ 06-04-2018 15:53:39.0933333 ║ 0 ║ 0 ║
    ║ 10 ║ 06-04-2018 15:53:39.2800000 ║ 0 ║ 0 ║
    ╚═════════╩═════════════════════════════╩═════════ ═════╩═══════════════════╝
    

    Além disso, em vez de usar uma abordagem RBAR para inserir dados na tabela de teste, você pode usar uma abordagem simples baseada em conjunto, como a abaixo:

    ;WITH src AS (
        SELECT n.Num
        FROM (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))n(Num)
    )
    INSERT INTO [dbo].[InMemoryStuff] (InMemoryId, Created) 
    SELECT 'Description' + CONVERT(varchar(30)
         , ((s1.Num * 10000) 
          + (s2.Num * 1000) 
          + (s3.Num * 100) 
          + (s4.Num * 10) 
          + (s5.Num)))
        , GETDATE()
    FROM src s1
        CROSS JOIN src s2
        CROSS JOIN src s3
        CROSS JOIN src s4
        CROSS JOIN src s5;
    

    No meu teste, ele preenche a tabela em menos de 3 segundos, enquanto a abordagem RBAR leva muito tempo . Além disso, bons comentários em seu código, me fizeram lol.

    • 10

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve