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 / 132293
Accepted
Geoff Patterson
Geoff Patterson
Asked: 2016-03-16 07:28:55 +0800 CST2016-03-16 07:28:55 +0800 CST 2016-03-16 07:28:55 +0800 CST

As tabelas de sistema do SQL Server podem ser desfragmentadas?

  • 772

Temos vários bancos de dados nos quais um grande número de tabelas é criado e descartado. Pelo que podemos dizer, o SQL Server não realiza nenhuma manutenção interna nas tabelas base do sistema , o que significa que elas podem se tornar muito fragmentadas com o tempo e aumentar de tamanho. Isso coloca pressão desnecessária no pool de buffers e também afeta negativamente o desempenho de operações, como calcular o tamanho de todas as tabelas em um banco de dados.

Alguém tem sugestões para minimizar a fragmentação nessas tabelas internas principais? Uma solução óbvia seria evitar a criação de tantas tabelas (ou criar todas as tabelas transitórias no tempdb), mas para o propósito desta questão, digamos que o aplicativo não tenha essa flexibilidade.

Editar: pesquisas adicionais mostram esta pergunta sem resposta , que parece intimamente relacionada e indica que alguma forma de manutenção manual ALTER INDEX...REORGANIZEpode ser uma opção.


Pesquisa inicial

Os metadados sobre essas tabelas podem ser visualizados em sys.dm_db_partition_stats:

-- The system base table that contains one row for every column in the system
SELECT row_count,
    (reserved_page_count * 8 * 1024.0) / row_count AS bytes_per_row, 
    reserved_page_count/128. AS space_mb
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('sys.syscolpars')
    AND index_id = 1
-- row_count:       15,600,859
-- bytes_per_row:   278.08
-- space_mb:        4,136

No entanto, sys.dm_db_index_physical_statsnão parece oferecer suporte à visualização da fragmentação dessas tabelas:

-- No fragmentation data is returned by sys.dm_db_index_physical_stats
SELECT *
FROM sys.dm_db_index_physical_stats(
    DB_ID(),
    OBJECT_ID('sys.syscolpars'),
    NULL,
    NULL,
    'DETAILED'
)

Os scripts de Ola Hallengren também contêm um parâmetro para considerar a desfragmentação de is_ms_shipped = 1objetos, mas o procedimento ignora silenciosamente as tabelas básicas do sistema mesmo com esse parâmetro ativado. Ola esclareceu que esse é o comportamento esperado; apenas tabelas de usuário (não tabelas de sistema) que são ms_shipped (por exemplo msdb.dbo.backupset, ) são consideradas.

-- Returns code 0 (successful), but does not do any work for system base tables.
-- Instead of the expected commands to update statistics and reorganize indexes,
-- no commands are generated. The script seems to assume the target tables will
-- appear in sys.tables, but this does not appear to be a valid assumption for
-- system tables like sys.sysrowsets or sys.syscolpars.
DECLARE @result int;
EXEC @result = IndexOptimize @Databases = 'Test',
        @FragmentationLow = 'INDEX_REORGANIZE',
        @FragmentationMedium = 'INDEX_REORGANIZE',
        @FragmentationHigh = 'INDEX_REORGANIZE',
        @PageCountLevel = 0,
        @UpdateStatistics = 'ALL',
        @Indexes = '%Test.sys.sysrowsets.%',
        -- Proc works properly if targeting a non-system table instead
        --@Indexes = '%Test.dbo.Numbers.%',
        @MSShippedObjects = 'Y',
        @Execute = 'N';
PRINT(@result);


Informações adicionais solicitadas

Eu usei uma adaptação da consulta de Aaron abaixo do uso do buffer pool da tabela de sistema de inspeção, e descobri que existem dezenas de GB de tabelas do sistema no buffer pool para apenas um banco de dados, com ~ 80% desse espaço sendo espaço livre em alguns casos .

-- Compute buffer pool usage by system table
SELECT OBJECT_NAME(p.object_id),
    COUNT(b.page_id) pages,
    SUM(b.free_space_in_bytes/8192.0) free_pages
FROM sys.dm_os_buffer_descriptors b
JOIN sys.allocation_units a
    ON a.allocation_unit_id = b.allocation_unit_id
JOIN sys.partitions p
    ON p.partition_id = a.container_id
    AND p.object_id < 1000 -- A loose proxy for system tables
WHERE b.database_id = DB_ID()
GROUP BY p.object_id
ORDER BY pages DESC

insira a descrição da imagem aqui

sql-server sql-server-2014
  • 2 2 respostas
  • 4325 Views

2 respostas

  • Voted
  1. Best Answer
    Aaron Bertrand
    2016-03-16T08:12:44+08:002016-03-16T08:12:44+08:00

    Tem certeza de que identificou de forma positiva e precisa esta tabela do sistema como a única fonte de "pressão desnecessária no pool de buffers e também afeta negativamente o desempenho de operações, como calcular o tamanho de todas as tabelas em um banco de dados"? Tem certeza de que esta tabela do sistema não é autogerenciada de forma que (a) a fragmentação seja minimizada ou mantida sob controle secretamente ou apenas (b) gerenciada com eficiência na memória para que os níveis de desfragmentação realmente não afetem muito?

    Você pode ver quantas páginas estão em uso e quanto espaço livre há nas páginas que estão na memória ( page_free_space_percentestá sempre NULLnas alocações DMF, mas está disponível no buffer DMV) - isso deve lhe dar uma ideia se o que você está se preocupando é realmente algo com o qual você deveria se preocupar:

    SELECT 
      Number_of_Pages = COUNT(*), 
      Number_of_Pages_In_Memory = COUNT(b.page_id),
      Avg_Free_Space = AVG(b.free_space_in_bytes/8192.0) 
    FROM sys.dm_db_database_page_allocations
    (
      DB_ID(),
      OBJECT_ID(N'sys.syscolpars'),
      NULL,NULL,'DETAILED'
    ) AS p
    LEFT OUTER JOIN sys.dm_os_buffer_descriptors AS b
    ON b.database_id = DB_ID() 
    AND b.page_id = p.allocated_page_page_id 
    AND b.file_id = p.allocated_page_file_id;
    

    Se o seu número de páginas for pequeno (como provavelmente <10.000 para tabelas do sistema) ou se o espaço livre for "baixo" (não tenho certeza de quais são seus limites típicos para reorganizar/reconstruir), concentre-se em outras frutas mais interessantes e acessíveis .

    Se o seu número de páginas for grande e o espaço livre for "alto", ok, talvez eu esteja dando muito crédito ao SQL Server por sua própria auto-manutenção. Como você mostrou na outra pergunta , isso funciona ...

    ALTER INDEX ALL ON sys.syscolpars REORGANIZE;
    

    ...e reduz a fragmentação . Embora possa exigir permissões elevadas (não tentei como peão).

    Talvez você possa fazer isso periodicamente como parte de sua própria manutenção, se isso fizer você se sentir bem e/ou se tiver alguma evidência de que tenha algum impacto positivo em seu sistema.

    • 11
  2. Geoff Patterson
    2016-03-17T12:06:51+08:002016-03-17T12:06:51+08:00

    Com base na orientação da resposta de Aaron, bem como em pesquisas adicionais, aqui está um rápido resumo da abordagem que fiz.

    Pelo que posso dizer, as opções para inspecionar a fragmentação das tabelas base do sistema são limitadas. Eu fui em frente e registrei um problema de conexão para fornecer melhor visibilidade, mas, enquanto isso, parece que as opções incluem coisas como examinar o buffer pool ou verificar o número médio de bytes por linha.

    Criei então um procedimento para executar `ALTER INDEX...REORGANIZE em todas as tabelas base do sistema . A execução desse procedimento em alguns de nossos servidores de desenvolvimento mais (ab) usados ​​mostrou que o tamanho cumulativo das tabelas básicas do sistema foi reduzido em até 50 GB (com ~ 5MM de tabelas de usuário no sistema, claramente um caso extremo).

    Uma de nossas tarefas de manutenção noturna, que ajuda a limpar muitas das tabelas de usuário criadas por vários testes de unidade e desenvolvimento, levava aproximadamente 50 minutos para ser concluída. Uma combinação de sp_whoisactive, sys.dm_os_waiting_tasks, e DBCC PAGEmostrou que as esperas eram dominadas por E/S nas tabelas de base do sistema.

    Após a reorganização de todas as tabelas base do sistema, a tarefa de manutenção caiu para ~15 minutos. Ainda havia algumas esperas de I/O, mas elas diminuíram significativamente, talvez devido a uma quantidade maior de dados restantes no cache e/ou mais readaheads devido à menor fragmentação.

    Portanto, minha conclusão é que adicionar ALTER INDEX...REORGANIZEtabelas de base do sistema em um plano de manutenção pode ser uma coisa útil a se considerar, mas provavelmente apenas se você tiver um cenário em que um número incomum de objetos está sendo criado em um banco de dados.

    • 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