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 / 346327
Accepted
Martin Smith
Martin Smith
Asked: 2025-04-27 05:41:16 +0800 CST2025-04-27 05:41:16 +0800 CST 2025-04-27 05:41:16 +0800 CST

Como o SQL Server mantém metadados de contagem de linhas?

  • 772

Para um exemplo de tabela rowstore...

CREATE TABLE T(Id INT PRIMARY KEY, C1 INT NULL, C2 INT NULL);

Existem vários métodos diferentes para recuperar contagens de linhas de tabela de metadados no SQL Server - como o abaixo

SELECT SUM(rows) 
FROM sys.partitions
WHERE object_id = object_id('dbo.T') AND index_id <= 1;

SELECT SUM(row_count) 
FROM sys.dm_db_partition_stats
WHERE object_id = object_id('dbo.T') AND index_id <= 1;

SELECT SUM(rows)
FROM sys.sysindexes
WHERE id = object_id('dbo.T') AND indid <= 1;

SELECT OBJECTPROPERTYEX(object_id('dbo.T'), 'Cardinality') 

Os planos de execução aparentemente mostram uma variedade de objetos diferentes sendo usados ​​- como o abaixo.

  • sysrowsets OUTER APPLY OpenRowset(TABLE ALUCOUNT
  • sysidxstats CROSS APPLY OpenRowSet(TABELA PARTITIONCOUNTS
  • sysidxstats i CROSS APPLY OpenRowSet(TABLE INDEXPROP

O que está acontecendo aqui? O SQL Server realmente mantém esses metadados em vários lugares? Se sim, qual é o método mais confiável?

sql-server
  • 2 2 respostas
  • 276 Views

2 respostas

  • Voted
  1. Martin Smith
    2025-04-27T05:41:16+08:002025-04-27T05:41:16+08:00

    Para analisar isso, criei um novo banco de dados conforme abaixo

    CREATE DATABASE RowCountTest
    
    GO
    
    USE RowCountTest
    
    SELECT physical_name FROM sys.database_files WHERE type_desc = 'ROWS'
    
    CREATE TABLE T(Id INT PRIMARY KEY, C1 INT NULL, C2 INT NULL);
    
    INSERT T(Id) SELECT TOP 100 object_id FROM sys.all_objects
    
    CHECKPOINT
    

    Isso criou um banco de dados com um único arquivo de dados e usei o Process Monitor para monitorar as operações de WriteFile nele. E então executei

    INSERT T(Id) VALUES (-1000),(-1001),(-1002)
    
    DELETE FROM T WHERE Id = -1001;
    
    INSERT T(Id) VALUES (-1003),(-1004);
    
    CHECKPOINT
    

    O ProcMon mostrou as seguintes páginas gravadas no disco

    insira a descrição da imagem aqui

    Tirando os deslocamentos disso para ver a quais objetos eles pertencem

    SELECT offset, 
           page_id, 
           CAST(page_id AS BINARY(4)) AS page_id_hex, 
           page_type_desc, 
           OBJECT_NAME(object_id) AS object_name
    FROM (VALUES  
        (8192),
        (1171456),
        (1318912),
        (1572864),
        (2293760),
        (73728)
    )V(offset)
    CROSS APPLY sys.dm_db_page_info(db_id(), 1, offset/8192, 'DETAILED')
    

    Devolvido

    desvio id_da_página id_da_página_hexadecimal descrição_do_tipo_de_página nome_do_objeto
    8192 1 0x00000001 PÁGINA_PFS NULO
    1171456 143 0x0000008F PÁGINA_DE_DADOS unidades de sistema
    1318912 161 0x000000A1 PÁGINA_DE_DADOS conjuntos de linhas de sistema
    1572864 192 0x000000C0 PÁGINA_DE_DADOS sistemas
    2293760 280 0x00000118 PÁGINA_DE_DADOS T
    73728 9 0x00000009 PÁGINA_DE_BOOT NULO

    sysallocunitsPossui colunas relevantes para contagens de páginas, mas nada sobre contagem de linhas, sysrscolscontém as contagens de modificações por coluna usadas para recompilações do plano de execução baseado em cardinalidade, mas, novamente, nenhuma coluna de contagem de linhas. A única dessas tabelas base do sistema que possui uma coluna de contagem de linhas está rcrowsem sysrowsets.

    Então concluo que todos esses métodos, em última análise, obtêm o valor do mesmo lugar, pois ele é armazenado persistentemente em apenas um lugar.

    Eu também executei o abaixo

    /*Undocumented trace flag to return inactive records in transaction log */
    DBCC TRACEON(2537)
    
    SELECT Operation, AllocUnitName, Description, [Page Id]
    FROM sys.fn_dblog(NULL, NULL)
    

    A parte relevante do log de transações após o primeiro manual CHECKPOINTestá abaixo

    insira a descrição da imagem aqui

    As várias LOP_COUNT_DELTAentradas mostram alguns aspectos interessantes

    • A coluna "Descrição" mostra exatamente o que eles estão definindo
    • Todos eles acontecem depois das LOP_COMMIT_XACTtransações do usuário (ou seja, não fazem parte dessas transações)
    • Os valores definidos são combinados a partir de várias transações diferentes (por exemplo, inserir 3 linhas, excluir 1 linha, inserir 2 linhas na tabela de 100 linhas, o que, em última análise, levou a uma única LOP_COUNT_DELTAconfiguração de entrada Row count: 104)

    Então, se a contagem de linhas em sysrowsets for atualizada apenas periodicamente, isso significa que os valores de metadados retornados estão incorretos?

    Todos os métodos fornecidos na pergunta ainda retornavam a contagem correta de linhas antes de serem gravadas sysrowsets. Presumo que a contagem seja atualizada para as estruturas de memória usadas pelos vários DMFs internos ( ALUCOUNT/ PARTITIONCOUNTS/ INDEXPROP).

    Eu até mesmo matei o processo do SQL Server antes que as alterações sysrowsetsfossem gravadas no disco e eles ainda retornaram os valores corretos após a reinicialização do serviço, então presumo que os deltas não verificados sejam recalculados como parte da recuperação do banco de dados.

    A contagem de linhas é documentada como algo que pode dar errado e precisar de correção, mas não tenho certeza de quais são as circunstâncias que podem causar isso.

    • 10
  2. Best Answer
    Paul White
    2025-04-27T19:38:41+08:002025-04-27T19:38:41+08:00

    O SQL Server realmente mantém esses metadados em vários locais? Se sim, qual é o método mais confiável?

    Todos os métodos listados na pergunta recuperam a contagem de linhas por meio de uma chamada para sqlmin!GrabRowsetCounts:

    partições sys
    sys.partitions

    sys.dm_db_partition_stats
    sys.dm_db_partition_stats

    sys.sysindexes
    sys.sysindexes

    OBJETOPROPRIEDADEEX
    OBJECTPROPERTYEX

    Como você observou, as informações são salvas apenas em uma tabela interna.

    Como rotina, as contagens de conjuntos de linhas são mantidas na memória para cada HoBt. Para operações por linha, isso significa literalmente que um contador é incrementado ou decrementado para cada modificação de linha, por exemplo, por meio de uma chamada para sqlmin!BaseSharedHoBt::DeltaRowCount.

    LOP_COUNT_DELTAOs registros de log para alterações líquidas são gravados em pontos de verificação por meio de sqlmin!FlushHoBtsDeltaCounts:

    Rastreamento de pilha de ponto de verificação

    Observe que muitos dos nomes de métodos indicam que eles não são transacionais.

    • 9

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