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 / user-284726

Arokh's questions

Martin Hope
Arokh
Asked: 2024-06-13 18:32:19 +0800 CST

Alto uso de memória para SqlBulkCopy

  • 7

Comecei a usar o QueryStore para monitorar meu App e uma das coisas que notei é o alto uso inesperado de memória para o que considerei uma operação simples:

insira a descrição da imagem aqui

O que significaria que a instrução usa quase 600 MB de RAM cada vez que é executada?
O RowCount para cada execução nesse período é muito menor que 100. A instrução em si é executada a cada 5 segundos.

A tabela é particionada e baseada em um índice ColumnStore e não possui outros índices ou chave primária/identidade e possui cerca de 750 mil linhas:

CREATE TABLE [DataLink].[LogEntry](
  [AppInstanceId] [bigint] NOT NULL,
  [LoggedOnUtc] [datetime2](7) NOT NULL,
  [CategoryName] [nvarchar](256) NOT NULL,
  [EventCode] [int] NOT NULL,
  [EventName] [nvarchar](256) NULL,
  [LogLevel] [int] NOT NULL,
  [ScopeJson] [nvarchar](max) NULL,
  [StateJson] [nvarchar](max) NULL,
  [ExceptionJson] [nvarchar](max) NULL,
  [Message] [nvarchar](max) NULL
) ON [PSCH_Logging_DataLink_LogEntry_Daily7Of9]([LoggedOnUtc])

CREATE CLUSTERED COLUMNSTORE INDEX [CIX_LogEntry] 
ON [DataLink].[LogEntry] WITH (DROP_EXISTING = OFF, COMPRESSION_DELAY = 0, DATA_COMPRESSION = COLUMNSTORE) 
ON [PSCH_Logging_DataLink_LogEntry_Daily7Of9]([LoggedOnUtc])

O Código que aciona as inserções:

using var conn = connInfo.Main.GetConnection(DatabaseLoginType.User);
await conn.OpenAsync(ct).CAf();
using var sqlBulkCopy = new SqlBulkCopy((SqlConnection)conn, SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers, null);

foreach(var toWriteItemGroup in toWriteItems.GroupBy(x => x.SchemaName)) {
...

    dataReader.Init(toWriteItemGroup, tableInfo.ColumnMappings.Length);

    sqlBulkCopy.DestinationTableName = $"{schemaName}.LogEntry";
    sqlBulkCopy.ColumnMappings.Clear();
    for(int i = 0; i < tableInfo.ColumnMappings.Length; i++) sqlBulkCopy.ColumnMappings.Add(i, tableInfo.ColumnMappings[i]);
    await sqlBulkCopy.WriteToServerAsync(dataReader, ct).CAf();
...
}

Alguma ideia de por que o uso de memória é tão alto e o que posso fazer para corrigir isso?

Edit4
Fiz alguns testes alterando e compilando manualmente o Microsoft.Data.SqlClient. As alterações que fiz incluíram a adição de ROWS_PER_BATCH e/ou KILOBYTES_PER_BATCH às opções with da instrução "insert bulk". Nenhuma das opções alterou a quantidade de memória usada, mas a primeira alterou a estimativa de contagem de linhas: https://www.brentozar.com/pastetheplan/?id=HkKjc9HIC Não parece que "inserir volume" possa ser otimizado para contagens baixas de linhas.

Edit3
Aqui está um pequeno exemplo com o qual posso reproduzir o problema.
Ele contém um script "Script.sql" que precisa ser executado primeiro para configurar a tabela e adicionar alguns dados. Depois disso execute o programa com "dotnet run" (ou use um IDE).
Como não consigo fazer upload de arquivos aqui, fiz o upload para o github Gist: https://gist.github.com/DvdKhl/d042ed05e3237136265295cb39ecb4f4

O roteiro irá:

  • Crie uma visualização que mostre PartitionInfo da tabela
  • Crie (ou recrie) a tabela e sua configuração
  • Insira 700 mil linhas (100 mil por partição)
  • Reconstrua o índice
  • Produza as informações da partição
  • Comentada é
    • Sessão de Evento (Evento Estendido) para capturar o plano de consulta
    • Outra declaração de inserção
    • Limpar

O Programa irá:

  • Abra uma conexão em “localhost” para o banco de dados “main”
  • Crie um DataReader fictício (alterar contagem para alterar a contagem de linhas inseridas)
  • Configure o SqlBulkCopy como acima
  • Chame WriteToServerAsync para inserir as linhas

Isso resulta no seguinte plano de consulta: https://www.brentozar.com/pastetheplan/?id=B1v_8bGLC

Edit2
Como sugerido por Denis Rubashkin, configurei BatchSize e uma dica de pedido:

sqlBulkCopy.BatchSize = toWriteItemGroup.Count();
sqlBulkCopy.ColumnOrderHints.Add("LoggedOnUtc", SortOrder.Ascending);

BatchSize parece não mudar nada (a estimativa permanece a mesma).
Parece que ROWS_PER_BATCH não é usado, embora sqlBulkCopy.BatchSize esteja definido no código, o que pode ser o principal problema.

Quando a dica Order é adicionada, a consulta não aparece no QueryStore.
O uso de eventos estendidos para obter o plano de consulta mostra um aviso de "Concessão excessiva". Então não tenho certeza se isso ajudou.

A opção KILOBYTES_PER_BATCH parece interessante, mas não parece que posso configurá-la no código C#.

WithOrderHint / WithoutOrderHint (tabela diferente, mas exatamente o mesmo problema)

Editar:
Plano de consulta: https://www.brentozar.com/pastetheplan/?id=SJGpBktH0

Propriedades da Tabela - Armazenamento
insira a descrição da imagem aqui

Uso de disco por partição
insira a descrição da imagem aqui

sql-server
  • 3 respostas
  • 213 Views
Martin Hope
Arokh
Asked: 2024-02-05 03:57:05 +0800 CST

Auditoria para acesso direto a objetos (ignorando acesso indireto)

  • 5

para isolar tabelas internas do acesso a bancos de dados de terceiros, criamos esquemas especificamente para esse caso de uso. Logins/usuários de banco de dados de terceiros só têm acesso a esses esquemas "públicos".
O problema é que o usuário tinha mais permissões do que deveria e muitas consultas de terceiros acessam as tabelas internas.
Como não posso remover as permissões abruptamente, gostaria de fazer isso aos poucos. Identificar consultas problemáticas e alterá-las de acordo.

Para isso tentei utilizar os recursos de Auditoria de Banco de Dados do Sql Server, mas parece que estou faltando informações para o que preciso:
Digamos que tenho a tabela [Internal].[Machine]e a View [Public].[Machine]que para simplificar é apenas select * from [Internal].[Machine]. O usuário viewersó tem permissão para selecionar [Public].[Machine].

Adicionar uma "especificação de auditoria de banco de dados" para (Type=SELECT, ObjectClass=SCHEMA, ObjectName=Internal, PrincipalName=viewer) produz uma entrada para select * from [Internal].[Machine]e select * from [Public].[Machine].
Meu objetivo é ter apenas uma entrada para select * from [Internal].[Machine], ou seja, quando o objeto for acessado diretamente pela instrução de consulta. E até onde vi, as linhas produzidas não contêm as informações necessárias para diferenciar as duas.

Isso é de alguma forma possível com o recurso Auditoria/Eventos Estendidos do Sql Server (ou algo completamente diferente)?

sql-server
  • 1 respostas
  • 86 Views
Martin Hope
Arokh
Asked: 2024-01-04 22:04:19 +0800 CST

Mudando a partição da tabela para uma tabela temporária

  • 5

Estou tentando mudar uma partição de tabela para uma tabela temporária com a seguinte consulta:

create partition function [PFCT_T](datetime2) as range right for values ()
create partition scheme [PSCH_T] as partition [PFCT_T] all to ([primary])
    
create table T(A1 datetime2 not null, A2 int not null) on [PSCH_T](A1)
create clustered columnstore index [CIX_T] on dbo.T
    
insert into T(A1, A2) values ('2024-01-01 00:00:00', 1)
    
select top 0 * into #T from T
create clustered columnstore index [CIX_#T] on #T
    
alter table T switch partition 1 to #T
--Results in:
--Msg 608, Level 16, State 1, Line 15
--No catalog entry found for partition ID 5620492390548766720 in database 23. The metadata is inconsistent. Run DBCC CHECKDB to check for a metadata corruption.

Não é possível mudar uma partição para uma tabela temporária (funciona com tabelas normais) ou perdi alguma coisa?

partitioning
  • 1 respostas
  • 22 Views

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