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 / 135940
Accepted
Alexei
Alexei
Asked: 2016-04-21 07:00:16 +0800 CST2016-04-21 07:00:16 +0800 CST 2016-04-21 07:00:16 +0800 CST

Otimização e manutenção de logs de banco de dados no SQL Server

  • 772

Um dos aplicativos da Web em que estou trabalhando usa NLog para registrar informações de contexto de depuração e erro no banco de dados. Basicamente, ele executa um número moderado de inserções (aprecio algumas dezenas de milhares por dia) usando o seguinte padrão:

<commandText>
  insert into dbo.nlog
  (log_date, log_level_id, log_level, logger, log_message, machine_name, log_user_name, call_site, thread, exception, stack_trace, full_exception_info)
  values(@timestamp, dbo.func_get_nlog_level_id(@level), @level, @logger, @message, @machinename, @username, @call_site, @threadid, @log_exception, @stacktrace, @FullExceptionInfo);
</commandText>
<parameter name="@timestamp" layout="${longdate}"/>
<parameter name="@level" layout="${level}"/>
<parameter name="@logger" layout="${logger}"/>
<parameter name="@message" layout="${message}"/>
<parameter name="@machinename" layout="${machinename}"/>
<parameter name="@username" layout="${windows-identity:domain=true}"/>
<parameter name="@call_site" layout="${callsite:filename=true}"/>
<parameter name="@threadid" layout="${threadid}"/>
<parameter name="@log_exception" layout="${exception}"/>
<parameter name="@stacktrace" layout="${stacktrace}"/>
<parameter name="@FullExceptionInfo" layout="${gdc:FullExceptionInfo}"/>

Para minimizar o impacto do registro, as consultas do banco de dados são emitidas de forma assíncrona (em um encadeamento diferente). No entanto, tenho que ter cuidado para não ficar sem threads do Thread Pool.

Para melhor desempenho na consulta do log, coloquei dois índices para as colunas mais utilizadas, log_data e log_user_name . No entanto, entendo que isso terá um impacto negativo no desempenho das inserções. Há também um índice clusterizado em enter_date , conforme mostrado por sp_help:

IX_nlog_entered_date clustered located on PRIMARY entered_date

P1: tudo bem ter esses índices ou é melhor não tê-los e sofrer a penalidade por raramente consultar a tabela? Ou talvez haja uma abordagem melhor.

A consulta é feita usando consultas simples como as seguintes:

-- just see the latest logged activity
SELECT TOP 1000 *
FROM nlog 
ORDER BY nlog_id DESC

ou assim:

SELECT TOP 200*
FROM nlog 
WHERE log_user_name = 'domain\username'
ORDER BY nlog_id DESC

Claramente, isso pode bloquear a tabela durante a execução, atrasando algumas inserções. Acho que usar WITH(NOLOCK)deveria ser uma boa opção, mas muitas vezes as pessoas se esquecem disso.

P2: como posso minimizar o impacto da leitura na mesa? Estou pensando em negar o acesso de leitura à tabela e, em vez disso, criar um procedimento armazenado para realizar a leitura com NOLOCK, mas isso leva a mais complexidade.

Depois de um tempo, os registros antigos devem ser excluídos. Pelo que sei, excluir muitas linhas de tabelas grandes é uma consulta pesada. A aplicação Web tem um período designado (à noite) para realizar trabalhos de manutenção, mas gostaria de melhorar esta etapa. Então, a terceira pergunta:

P3: como posso minimizar o impacto de grandes exclusões? . Estou pensando em particionar tabelas por entered_date(tem o padrão deGETDATE() ), mas não sei se é uma boa ideia.

Definições de tabelas e índices

CREATE TABLE [dbo].[nlog](
    [nlog_id] [int] IDENTITY(1,1) NOT NULL,
    [entered_date] [datetime2](7) NOT NULL CONSTRAINT [DF_nlog_log_time]  DEFAULT (getdate()),
    [log_app_name] [nvarchar](255) NULL,
    [log_date] [nvarchar](64) NULL,
    [log_level_id] [tinyint] NOT NULL,
    [log_level] [nvarchar](64) NULL,
    [logger] [nvarchar](1024) NULL,
    [log_message] [nvarchar](max) NULL,
    [machine_name] [nvarchar](255) NULL,
    [log_user_name] [nvarchar](255) NULL,
    [call_site] [nvarchar](4000) NULL,
    [thread] [nvarchar](255) NULL,
    [exception] [nvarchar](max) NULL,
    [stack_trace] [nvarchar](max) NULL,
    [full_exception_info] [nvarchar](max) NULL,
 CONSTRAINT [PK_nlog] PRIMARY KEY NONCLUSTERED 
(
    [nlog_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

CREATE CLUSTERED INDEX [IX_nlog_entered_date] ON [dbo].[nlog]
(
    [entered_date] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) ON [PRIMARY]
GO
sql-server sql-server-2012
  • 2 2 respostas
  • 864 Views

2 respostas

  • Voted
  1. Best Answer
    Paul White
    2016-04-26T03:41:00+08:002016-04-26T03:41:00+08:00
    1. Índices

      A decisão de adicionar um ou mais índices não clusterizados é uma avaliação que só você pode fazer com precisão, com base nos resultados do teste e levando em consideração suas prioridades locais. Dito isso, o impacto no desempenho de adicionar um pequeno número de índices não clusterizados estreitos geralmente é pequeno, do ponto de vista do banco de dados.

      De forma mais geral, a indexação deve ser orientada por prioridades, opções de design e carga de trabalho. Seu esquema parece diferir do padrão NLog por ter nlog_id como uma chave primária não clusterizada, com o índice clusterizado em enter_date . Supondo que essa foi uma decisão deliberada, a maioria das consultas na tabela deve ser baseada em um intervalo de datas, em vez dos top (n) ... order by nlog_idexemplos fornecidos na pergunta. Seus exemplos provavelmente prefeririam uma chave primária clusterizada e um índice não clusterizado na data_entrada .

      Com 50.000 linhas por dia, a tabela cresce apenas cerca de 18 milhões de linhas por ano. Este é um número muito pequeno no esquema das coisas. A pergunta não menciona explicitamente nenhum problema de desempenho atual, seja para leituras ou gravações.

    2. Leitura

      O acesso a consultas ad hoc é difícil de gerenciar. Com acesso direto à tabela, não há nada que impeça que alguém escreva um desastre de uma consulta (por exemplo, uma junção cruzada paralela acidental) que possa afetar a instância como um todo.

      Fornecer acesso apenas por meio de exibições, procedimentos armazenados e funções com valor de tabela embutida geralmente é uma ideia muito melhor. Se a tabela de log for apenas anexada fora das janelas de manutenção, pode ser apropriado usar o nível de isolamento de leitura não confirmada (explicitamente) nos novos módulos de acesso a dados.

      Como alternativa, se o aplicativo puder tolerar uma alteração da implementação de bloqueio padrão de isolamento de leitura confirmada, você pode verificar a habilitação da implementação de controle de versão de linha (MVCC) conhecida como isolamento de instantâneo de leitura confirmada (RCSI) no SQL Server. Esta não é uma mudança a ser feita levianamente.

    3. Exclusões grandes

      Não é possível dizer se o particionamento é a solução certa para você com base nas informações fornecidas na pergunta. O principal benefício do particionamento é permitir a exclusão ou arquivamento praticamente instantâneo de toda a partição . Existem complexidades e custos envolvidos no lado da manutenção para conseguir isso, e o particionamento pode ter efeitos complexos nos planos de execução de consultas existentes que precisariam ser testados.

      Se a exclusão/arquivamento for relativamente regular e realizada durante uma janela de manutenção, a abordagem simples pode ser a melhor. A exclusão sempre pode ser executada em lotes de tamanho adequado, com backups de log de transação entre os backups conforme necessário.

    4. Inserções

      Se o sistema puder tolerar um pequeno atraso antes que os dados de log apareçam na tabela, as inserções provavelmente devem ser agrupadas, talvez usando os próprios recursos de buffer do NLog. Eu não uso o NLog, mas a documentação sugere várias opções de buffer que você deve procurar.

      Dada a taxa atual de inserções, isso provavelmente não é necessário do ponto de vista do banco de dados. Dito isso, inserir (digamos) cem linhas em uma única transação será mais eficiente do que cem transações separadas inserindo uma linha por vez.

    • 4
  2. Julian
    2016-04-21T13:32:05+08:002016-04-21T13:32:05+08:00

    Ler e escrever muito em uma tabela pode ser difícil de manter o desempenho. Os índices podem realmente prejudicar o desempenho da inserção e o bloqueio também é um aspecto importante a ser lembrado.

    Existe outra maneira de corrigir esses problemas - não grave diretamente no banco de dados. Por exemplo, grave as mensagens no MSMQ e use um serviço do Windows para inseri-las (em lote) no banco de dados. Então índices, bloqueio e exclusão não são mais problemas.

    • 1

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