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 / 191825
Accepted
James Lupolt
James Lupolt
Asked: 2017-11-28 10:31:43 +0800 CST2017-11-28 10:31:43 +0800 CST 2017-11-28 10:31:43 +0800 CST

Por que uma consulta SELECT causa gravações?

  • 772

Percebi que em um servidor que executa o SQL Server 2016 SP1 CU6, às vezes, uma sessão de eventos estendidos mostra uma consulta SELECT causando gravações. Por exemplo:

insira a descrição da imagem aqui

O plano de execução não mostra nenhuma causa óbvia para as gravações, como uma tabela de hash, spool ou classificação que pode ser derramada no TempDB:

insira a descrição da imagem aqui

A atribuição de variável a um tipo MAX ou uma atualização automática de estatísticas também pode causar isso, mas também não foi a causa das gravações nesse caso.

De que mais poderiam ser as gravações?

sql-server sql-server-2016
  • 3 3 respostas
  • 8495 Views

3 respostas

  • Voted
  1. James Lupolt
    2017-11-28T11:08:52+08:002017-11-28T11:08:52+08:00

    Em alguns casos, o Repositório de Consultas pode fazer com que as gravações ocorram como efeito de uma instrução select e na mesma sessão.

    Isso pode ser reproduzido da seguinte forma:

    USE master;
    GO
    CREATE DATABASE [Foo];
    ALTER DATABASE [Foo] SET QUERY_STORE (OPERATION_MODE = READ_WRITE, 
      CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30), 
      DATA_FLUSH_INTERVAL_SECONDS = 900, 
      INTERVAL_LENGTH_MINUTES = 60, 
      MAX_STORAGE_SIZE_MB = 100, 
      QUERY_CAPTURE_MODE = ALL, 
      SIZE_BASED_CLEANUP_MODE = AUTO);
    USE Foo;
    CREATE TABLE Test (a int, b nvarchar(max));
    INSERT INTO Test SELECT 1, 'string';
    

    Crie uma sessão de eventos estendidos para monitoramento:

    CREATE EVENT SESSION [Foo] ON SERVER 
    ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1)
        ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_name,sqlserver.is_system,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_server_principal_name,sqlserver.sql_text)
        WHERE ([writes]>(0))),
    ADD EVENT sqlserver.sql_batch_completed(SET collect_batch_text=(1)
        ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_name,sqlserver.is_system,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_server_principal_name,sqlserver.sql_text)
        WHERE ([writes]>(0)))
    ADD TARGET package0.event_file(SET filename=N'C:\temp\FooActivity2016.xel',max_file_size=(11),max_rollover_files=(999999))
    WITH (MAX_MEMORY=32768 KB,EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF);
    

    Em seguida execute o seguinte:

    WHILE @@TRANCOUNT > 0 COMMIT
    SET IMPLICIT_TRANSACTIONS ON;
    SET NOCOUNT ON;
    GO
    DECLARE @b nvarchar(max);
    SELECT @b = b FROM dbo.Test WHERE a = 1;
    WAITFOR DELAY '00:00:01.000';
    GO 86400
    

    Uma transação implícita pode ou não ser necessária para reproduzir isso.

    Por padrão, no início da próxima hora, o trabalho de coleta de estatísticas do Repositório de Consultas gravará os dados. Isso parece (às vezes?) ocorrer como parte da primeira consulta do usuário executada durante a hora. A sessão Extended Events mostrará algo semelhante ao seguinte:

    insira a descrição da imagem aqui

    O log de transações mostra as gravações que ocorreram:

    USE Foo;
    SELECT [Transaction ID], [Begin Time], SPID, Operation, 
      [Description], [Page ID], [Slot ID], [Parent Transaction ID] 
    FROM sys.fn_dblog(null,null) 
    /* Adjust based on contents of your transaction log */
    WHERE [Transaction ID] IN ('0000:0000042c', '0000:0000042d', '0000:0000042e')
    OR [Parent Transaction ID] IN ('0000:0000042c', '0000:0000042d', '0000:0000042e')
    ORDER BY [Current LSN];
    

    insira a descrição da imagem aqui

    Inspecionar a página com DBCC PAGEmostra que as gravações são para sys.plan_persist_runtime_stats_interval.

    USE Foo;
    DBCC TRACEON(3604); 
    DBCC PAGE(5,1,344,1); SELECT
    OBJECT_NAME(229575856);
    

    Observe que as entradas de log mostram três transações aninhadas, mas apenas dois registros de confirmação. Em uma situação semelhante na produção, isso levou a uma biblioteca cliente possivelmente defeituosa que usava transações implícitas iniciando inesperadamente uma transação de gravação, impedindo a limpeza do log de transações. A biblioteca foi escrita para emitir um commit somente após executar uma instrução update, insert ou delete, então ela nunca emitiu um comando commit e deixou uma transação de escrita aberta.

    • 39
  2. Erik Darling
    2017-11-28T11:41:24+08:002017-11-28T11:41:24+08:00

    Há outro momento em que isso pode acontecer, e é com uma atualização automática de estatísticas.

    Aqui está a sessão XE que veremos:

    CREATE EVENT SESSION batches_and_stats
        ON SERVER
        ADD EVENT sqlserver.auto_stats
        ( ACTION ( sqlserver.sql_text )),
        ADD EVENT sqlserver.sql_batch_completed
        ( ACTION ( sqlserver.sql_text ))
        ADD TARGET package0.event_file
        ( SET filename = N'c:\temp\batches_and_stats' )
        WITH ( MAX_MEMORY = 4096KB,
               EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
               MAX_DISPATCH_LATENCY = 30 SECONDS,
               MAX_EVENT_SIZE = 0KB,
               MEMORY_PARTITION_MODE = NONE,
               TRACK_CAUSALITY = OFF,
               STARTUP_STATE = OFF );
    GO
    

    Em seguida, usaremos isso para coletar informações:

    USE tempdb
    
    DROP TABLE IF EXISTS dbo.SkewedUp
    
    CREATE TABLE dbo.SkewedUp (Id INT NOT NULL, INDEX cx_su CLUSTERED (Id))
    
    INSERT dbo.SkewedUp WITH ( TABLOCK ) ( Id )
    SELECT CASE WHEN x.r % 15 = 0 THEN 1
                WHEN x.r % 5 = 0 THEN 1000
                WHEN x.r % 3 = 0 THEN 10000
                ELSE 100000
           END AS Id
    FROM   (   SELECT     TOP 1000000 ROW_NUMBER() OVER ( ORDER BY @@DBTS ) AS r
               FROM       sys.messages AS m
               CROSS JOIN sys.messages AS m2 ) AS x;
    
    
    ALTER EVENT SESSION [batches_and_stats] ON SERVER STATE = START
    
    SELECT su.Id, COUNT(*) AS records
    FROM dbo.SkewedUp AS su
    WHERE su.Id > 0
    GROUP BY su.Id
    
    ALTER EVENT SESSION [batches_and_stats] ON SERVER STATE = STOP
    

    Alguns dos resultados interessantes da Sessão XE:

    NOZES

    A atualização automática das estatísticas não mostra nenhuma gravação, mas a consulta mostra uma gravação imediatamente após a atualização das estatísticas.

    • 26
  3. Best Answer
    Erik Darling
    2019-02-21T17:44:38+08:002019-02-21T17:44:38+08:00

    Desajeitado

    Não me lembro se incluí isso na minha resposta original , então aqui está outro casal.

    Carretéis!

    O SQL Server tem muitos spools diferentes, que são estruturas de dados temporárias armazenadas em tempdb. Dois exemplos são os spools de Tabela e Índice.

    Quando ocorrerem em um plano de consulta, as gravações nesses spools serão associadas à consulta.

    NOZES

    Estes também serão registrados como gravações em DMVs, profiler, XE, etc.

    Carretel de índice

    NOZES

    Carretel de mesa

    NOZES

    A quantidade de gravações executadas aumentará com o tamanho dos dados em spool, obviamente.

    Derramamentos

    Quando o SQL Server não obtém memória suficiente para determinados operadores, ele pode derramar algumas páginas no disco. Isso acontece principalmente com classificações e hashes. Você pode ver isso em planos de execução reais e, em versões mais recentes do SQL Server, os spills também são rastreados em dm_exec_query_stats .

    SELECT deqs.sql_handle,
           deqs.total_spills,
           deqs.last_spills,
           deqs.min_spills,
           deqs.max_spills
    FROM sys.dm_exec_query_stats AS deqs
    WHERE deqs.min_spills > 0;
    

    NOZES

    NOZES

    Rastreamento

    Você pode usar uma sessão XE semelhante à que usei acima para ver isso em suas próprias demonstrações.

    CREATE EVENT SESSION spools_and_spills
        ON SERVER
        ADD EVENT sqlserver.sql_batch_completed
        ( ACTION ( sqlserver.sql_text ))
        ADD TARGET package0.event_file
        ( SET filename = N'c:\temp\spools_and_spills' )
        WITH ( MAX_MEMORY = 4096KB,
               EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
               MAX_DISPATCH_LATENCY = 1 SECONDS,
               MAX_EVENT_SIZE = 0KB,
               MEMORY_PARTITION_MODE = NONE,
               TRACK_CAUSALITY = OFF,
               STARTUP_STATE = OFF );
    GO
    
    • 12

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