Como se investiga o desempenho de uma instrução BULK INSERT?

12

Sou principalmente desenvolvedor .NET usando o Entity Framework ORM. No entanto, como não quero deixar de usar o ORM , estou tentando entender o que acontece na camada de dados (banco de dados). Basicamente, durante o desenvolvimento, inicio o criador de perfil e verifico o que algumas partes do código geram em termos de consultas.

Se eu encontrar algo totalmente complicado (o ORM pode gerar consultas terríveis, mesmo a partir de instruções LINQ bastante simples, se não escritas com cuidado) e / ou pesado (duração, CPU, leitura de página), eu o uso no SSMS e verifico seu plano de execução.

Funciona bem para o meu nível de conhecimento de banco de dados. No entanto, BULK INSERT parece ser uma criatura especial, pois não parece produzir um SHOWPLAN .

Vou tentar ilustrar um exemplo muito simples:

Definição de tabela

CREATE TABLE dbo.ImportingSystemFileLoadInfo
(
    ImportingSystemFileLoadInfoId INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_ImportingSystemFileLoadInfo PRIMARY KEY CLUSTERED,
    EnvironmentId INT NOT NULL CONSTRAINT FK_ImportingSystemFileLoadInfo REFERENCES dbo.Environment,
    ImportingSystemId INT NOT NULL CONSTRAINT FK_ImportingSystemFileLoadInfo_ImportingSystem REFERENCES dbo.ImportingSystem,
    FileName NVARCHAR(64) NOT NULL,
FileImportTime DATETIME2 NOT NULL,
    CONSTRAINT UQ_ImportingSystemImportInfo_EnvXIs_TableName UNIQUE (EnvironmentId, ImportingSystemId, FileName, FileImportTime)
)

Nota: nenhum outro índice está definido na tabela

A inserção em massa (o que eu pego no criador de perfil, apenas um lote)

insert bulk [dbo].[ImportingSystemFileLoadInfo] ([EnvironmentId] Int, [ImportingSystemId] Int, [FileName] NVarChar(64) COLLATE Latin1_General_CI_AS, [FileImportTime] DateTime2(7))

Métricas

  • 695 itens inseridos
  • CPU = 31
  • Lê = 4271
  • Gravações = 24
  • Duração = 154
  • Contagem total de tabelas = 11500

Para o meu aplicativo, tudo bem, embora as leituras pareçam bastante grandes (sei muito pouco sobre os componentes internos do SQL Server, então comparo com o tamanho da página de 8K e as pequenas informações de registro que tenho)

Pergunta: como posso investigar se esse BULK INSERT pode ser otimizado? Ou isso não faz sentido, pois é sem dúvida a maneira mais rápida de enviar grandes dados de um aplicativo cliente para o SQL Server?

Alexei
fonte

Respostas:

14

Tanto quanto posso dizer, você pode otimizar uma inserção em massa de uma maneira muito semelhante à de uma inserção regular. Normalmente, um plano de consulta para uma inserção simples não é muito informativo; portanto, não se preocupe em não ter o plano. Analisarei algumas maneiras de otimizar uma inserção, mas a maioria delas provavelmente não se aplica à inserção especificada na pergunta. No entanto, eles podem ser úteis se, no futuro, você precisar carregar grandes quantidades de dados.

1. Insira os dados na ordem das chaves de cluster

O SQL Server geralmente classifica os dados antes de inseri-los em uma tabela com um índice clusterizado. Para algumas tabelas e aplicativos, você pode melhorar o desempenho classificando os dados no arquivo simples e informando o SQL Server que os dados são classificados pelo ORDERargumento de BULK INSERT:

PEDIDO ({coluna [ASC | DESC]} [, ... n])

Especifica como os dados no arquivo de dados são classificados. O desempenho da importação em massa é aprimorado se os dados que estão sendo importados forem classificados de acordo com o índice em cluster da tabela, se houver.

Como você está usando uma IDENTITYcoluna como chave em cluster, não precisa se preocupar com isso.

2. Use TABLOCKse possível

Se você tiver apenas uma sessão inserindo dados em sua tabela, poderá especificar o TABLOCKargumento para BULK INSERT. Isso pode reduzir a contenção de bloqueio e pode levar ao registro mínimo em alguns cenários. No entanto, você está inserindo em uma tabela com um índice clusterizado que já contém dados, para que você não obtenha log mínimo sem o sinalizador de rastreamento 610, mencionado posteriormente nesta resposta.

Se TABLOCKnão for possível, porque você não pode alterar o código , nem toda a esperança se perde. Considere usar sp_table_option:

EXEC [sys].[sp_tableoption]
    @TableNamePattern = N'dbo.BulkLoadTable' ,
    @OptionName = 'table lock on bulk load' , 
    @OptionValue = 'ON'

Outra opção é ativar o sinalizador de rastreamento 715 .

3. Use um tamanho de lote apropriado

Às vezes, você poderá ajustar as inserções alterando o tamanho do lote.

ROWS_PER_BATCH = linhas_per_batch

Indica o número aproximado de linhas de dados no arquivo de dados.

Por padrão, todos os dados no arquivo de dados são enviados ao servidor como uma única transação, e o número de linhas no lote é desconhecido para o otimizador de consulta. Se você especificar ROWS_PER_BATCH (com um valor> 0), o servidor utilizará esse valor para otimizar a operação de importação em massa. O valor especificado para ROWS_PER_BATCH deve ser aproximadamente o mesmo que o número real de linhas. Para obter informações sobre considerações de desempenho, consulte "Comentários", posteriormente neste tópico.

Aqui está a citação de mais adiante neste artigo:

Se o número de páginas a serem liberadas em um único lote exceder um limite interno, poderá ocorrer uma varredura completa do buffer pool para identificar quais páginas serão liberadas quando o lote for confirmado. Essa verificação completa pode prejudicar o desempenho da importação em massa. Um provável caso de exceder o limite interno ocorre quando um buffer pool grande é combinado com um subsistema de E / S lento. Para evitar estouros de buffer em máquinas grandes, não use a dica TABLOCK (que removerá as otimizações em massa) ou use um tamanho de lote menor (que preserva as otimizações em massa).

Como os computadores variam, recomendamos que você teste vários tamanhos de lote com a carga de dados para descobrir o que funciona melhor para você.

Pessoalmente, eu insira todas as 695 linhas em um único lote. O ajuste do tamanho do lote pode fazer uma grande diferença ao inserir muitos dados.

4. Verifique se você precisa da IDENTITYcoluna

Não sei nada sobre seu modelo ou requisitos de dados, mas não caia na armadilha de adicionar uma IDENTITYcoluna a todas as tabelas. Aaron Bertrand tem um artigo sobre isso chamado Maus hábitos: colocar uma coluna de IDENTIDADE em todas as tabelas . Para ficar claro, não estou dizendo que você deve remover a IDENTITYcoluna desta tabela. No entanto, se você determinar que a IDENTITYcoluna não é necessária e removê-la, isso poderá melhorar o desempenho da pastilha.

5. Desative índices ou restrições

Se você estiver carregando uma grande quantidade de dados em uma tabela em comparação com o que você já possui, pode ser mais rápido desativar índices ou restrições antes do carregamento e ativá-los após o carregamento. Para grandes quantidades de dados, geralmente é mais ineficiente para o SQL Server criar um índice de uma só vez, em vez de os dados serem carregados na tabela. Parece que você inseriu 695 linhas em uma tabela com 11500 linhas, portanto, eu não recomendaria essa técnica.

6. Considere TF 610

O Trace Flag 610 permite o registro mínimo em alguns cenários adicionais. Para sua tabela com uma IDENTITYchave em cluster, você obteria um registro mínimo para novas páginas de dados, desde que seu modelo de recuperação seja simples ou com registro em massa. Acredito que esse recurso não esteja ativado por padrão, pois pode prejudicar o desempenho em alguns sistemas. Você precisaria testar cuidadosamente antes de ativar esse sinalizador de rastreamento. A referência recomendada da Microsoft ainda parece ser The Data Loading Performance Guide

Impacto de E / S do registro mínimo sob sinalizador de rastreamento 610

Quando você confirma uma transação de carregamento em massa que foi minimamente registrada, todas as páginas carregadas devem ser liberadas para o disco antes que a confirmação seja concluída. Quaisquer páginas liberadas não capturadas por uma operação anterior do ponto de verificação podem criar uma grande quantidade de E / S aleatória. Compare isso com uma operação totalmente registrada, que cria E / S sequenciais nas gravações de log e não exige que as páginas carregadas sejam liberadas para o disco no momento da confirmação.

Se o seu cenário de carregamento for pequenas operações de inserção em árvores que não cruzam os limites do ponto de verificação e você tiver um sistema de E / S lento, o uso de log mínimo poderá realmente diminuir a velocidade da inserção.

Até onde eu sei, isso não tem nada a ver com o sinalizador de rastreamento 610, mas com o mínimo de registro em si. Acredito que a citação anterior sobre o ROWS_PER_BATCHajuste estava chegando ao mesmo conceito.

Em conclusão, provavelmente não há muito que você possa fazer para ajustar o seu BULK INSERT. Eu não ficaria preocupado com a contagem de leituras que você observou com sua inserção. O SQL Server relatará leituras sempre que você inserir dados. Considere o seguinte muito simples INSERT:

DROP TABLE IF EXISTS X_TABLE;

CREATE TABLE X_TABLE (
VAL VARCHAR(1000) NOT NULL
);

SET STATISTICS IO, TIME ON;

INSERT INTO X_TABLE WITH (TABLOCK)
SELECT REPLICATE('Z', 1000)
FROM dbo.GetNums(10000); -- generate 10000 rows

Saída de SET STATISTICS IO, TIME ON:

Tabela 'X_TABLE'. Contagem de varreduras 0, leituras lógicas 11428

Eu tenho 11428 leituras relatadas, mas isso não é uma informação acionável. Às vezes, o número de leituras relatadas pode ser reduzido com o mínimo de log, mas é claro que a diferença não pode ser traduzida diretamente em um ganho de desempenho.

Joe Obbish
fonte
12

Começarei a responder a essa pergunta, com a intenção de atualizá-la continuamente à medida que construo uma base de conhecimento de truques. Espero que outras pessoas se deparem com isso e me ajudem a melhorar meu próprio conhecimento no processo.

  1. Verificação do intestino: Seu firewall está realizando uma inspeção profunda e de estado dos pacotes? Você não encontrará muito na Internet sobre isso, mas se suas inserções em massa forem 10 vezes mais lentas do que deveriam, é provável que você tenha um dispositivo de segurança realizando uma inspeção profunda de pacotes de nível 3-7 e verificando "Prevenção de injeção genérica de SQL "

  2. Meça o tamanho dos dados que você planeja inserir em massa, em bytes, por lote. E verifique se está armazenando dados LOB, pois é uma operação de busca e gravação de página separada.

    Várias razões pelas quais você deve fazer desta maneira:

    uma. Na AWS, as IOPS do Elastic Block Storage são divididas em bytes, não em linhas.

    1. Consulte Desempenho do volume do Amazon EBS em instâncias Linux »Características e monitoramento de E / S para obter uma explicação sobre o que é uma unidade EBS IOPS
    2. Especificamente, os volumes SSD de uso geral (gp2) têm o conceito "Créditos de E / S e desempenho de ruptura" e é comum que o processamento pesado de ETL diminua os créditos de saldo de ruptura. A duração da sua explosão é medida em bytes, não em linhas do SQL Server :)

    b. Embora a maioria das bibliotecas ou documentos técnicos seja testada com base no número de linhas, é realmente o número de páginas que podem ser gravadas e, para calcular isso, você precisa saber quantos bytes por linha e o tamanho da página (geralmente 8 KB , mas sempre verifique se você herdou o sistema de outra pessoa.)

    SELECT *
    FROM 
    sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N'YourTable'), NULL, NULL, 'DETAILED')

    Preste atenção em avg_record_size_in_bytes e page_count.

    c. Como Paul White explica em https://sqlperformance.com/2019/05/sql-performance/minimal-logging-insert-select-heap , "Para habilitar o log mínimo INSERT...SELECT, o SQL Server deve esperar mais de 250 linhas com um tamanho total de pelo menos uma extensão (8 páginas). "

  3. Se você tiver algum índice com restrições de verificação ou restrições exclusivas, use SET STATISTICS IO ONe SET STATISTICS TIME ON(ou SQL Server Profiler ou SQL Server Extended Events) para capturar informações como se sua inserção em massa tem alguma operação de leitura. As operações de leitura são devidas ao mecanismo de banco de dados do SQL Server, garantindo que as restrições de integridade sejam aprovadas.

  4. Tente criar um banco de dados de teste em que o PRIMARYFILEGROUP esteja montado em uma unidade de RAM. Isso deve ser um pouco mais rápido que o SSD, mas também eliminar qualquer dúvida sobre se o seu controlador RAID pode estar sobrecarregando. Em 2018, não deveria, mas criando várias linhas de base diferenciais como esta, você pode ter uma idéia geral de quanto sobrecarga seu hardware está adicionando.

  5. Coloque também o arquivo de origem em uma unidade de RAM.

    Colocar o arquivo de origem em uma unidade RAM excluirá qualquer problema de contenção se você estiver lendo o arquivo de origem na mesma unidade em que o FILEGROUP do servidor de banco de dados estiver ativado.

  6. Verifique se você formatou seu disco rígido usando extensões de 64 KB.

  7. Use UserBenchmark.com e compare seu SSD. Isso vai:

    1. Adicione mais conhecimento a outros aficionados por desempenho sobre o desempenho esperado de um dispositivo
    2. Ajudá-lo a descobrir se o desempenho da sua unidade está com desempenho abaixo do mesmo nível da mesma unidade exata
    3. Ajudá-lo a descobrir se o desempenho de sua unidade está abaixo do desempenho de outras unidades da mesma categoria (SSD, HDD etc.)
  8. Se você estiver chamando "INSERT BULK" de C # por meio das extensões do Entity Framework, certifique-se de "aquecer" o JIT primeiro e "jogar fora" os primeiros resultados.

  9. Tente criar contadores de desempenho para o seu programa. Com o .NET, você pode usar o benchmark.NET e ele cria automaticamente um perfil de várias métricas básicas. Você pode COMPARTILHAR suas tentativas de criação de perfil com a comunidade de código-fonte aberto e ver se as pessoas que executam hardware diferente relatam as mesmas métricas (a partir do meu ponto anterior sobre o uso do UserBenchmark.com para comparar).

  10. Tente usar pipes nomeados e executá-lo como host local.

  11. Se você estiver direcionando o SQL Server e usando o .NET Core, considere criar um Linux com o SQL Server Std Edition - isso custa menos de um dólar por hora, mesmo para hardware sério. A principal vantagem de tentar o mesmo código com o mesmo hardware com um sistema operacional diferente é verificar se a pilha TCP / IP do kernel do sistema operacional está causando problemas.

  12. Use as consultas de diagnóstico do SQL Barry, de Glen Barry, para medir a latência da unidade que armazena o FILEGROUP da sua tabela de banco de dados.

    uma. Certifique-se de medir antes e depois do teste. O "antes do teste" apenas informa se você tem características horríveis de IO como linha de base.

    b. Para medir "durante o teste", você realmente precisa usar os contadores de desempenho PerfMon.

    Por quê? Porque a maioria dos servidores de banco de dados usa algum tipo de NAS (Network Attached Storage). Na nuvem, na AWS, o Elastic Block Storage é exatamente isso. Você pode estar vinculado ao IOPS da sua solução de volume / NAS EBS.

  13. Use alguma ferramenta para medir as estatísticas de espera. O Red Gate SQL Monitor , o SolarWinds Database Performance Analyzer ou mesmo as consultas de diagnóstico do SQL Server de Glen Barry ou a consulta de estatísticas de espera de Paul Randal .

    uma. Os tipos de espera mais comuns provavelmente serão Memória / CPU, WRITELOG, PAGEIOLATCH_EX e ASYNC_NETWORK_IO .

    b. Você pode incorrer em tipos de espera adicionais se estiver executando Grupos de Disponibilidade.

  14. Meça os efeitos de vários INSERT BULKcomandos simultâneos com TABLOCKdesativado (o TABLOCK provavelmente forçará a serialização dos comandos INSERT BULK). Seu gargalo pode estar aguardando INSERT BULKa conclusão; você deve tentar enfileirar tantas dessas tarefas quanto o modelo de dados físico do servidor de banco de dados puder suportar.

  15. Considere particionar sua tabela. Como um exemplo específico: se sua tabela de banco de dados for apenas anexável, Andrew Novick sugeriu a criação de um "TODAY" FILEGROUPe o particionamento em pelo menos dois grupos de arquivos, TODAY e BEFORE_TODAY. Dessa forma, se seus INSERT BULKdados são apenas dados de hoje, você pode filtrar um campo CreatedOn para forçar todas as inserções a atingir uma única FILEGROUPe, assim, reduzir o bloqueio ao usar TABLOCK. Essa técnica é descrita em mais detalhes em um documento técnico da Microsoft: tabela particionada e estratégias de índice usando o SQL Server 2008

  16. Se você estiver usando índices columnstore, desative TABLOCKe carregue dados em 102.400 linhas Tamanho do Lote. Em seguida, você pode carregar todos os seus dados em paralelo diretamente nos grupos de linhas columnstore. Esta sugestão (e racional documentada) vem dos índices Columnstore da Microsoft - Orientação para carregamento de dados :

    O carregamento em massa tem as seguintes otimizações de desempenho integradas:

    Cargas paralelas: você pode ter várias cargas em massa simultâneas (bcp ou inserção em massa), cada uma carregando um arquivo de dados separado. Ao contrário dos carregamentos em massa do armazenamento de linhas no SQL Server, você não precisa especificar, TABLOCKporque cada encadeamento de importação em massa carregará dados exclusivamente em grupos de linhas separados (grupos de linhas compactados ou delta) com bloqueio exclusivo. O uso TABLOCKforçará um bloqueio exclusivo na tabela e você não poderá importar dados em paralelo.

    Registro mínimo:Um carregamento em massa usa o registro mínimo de dados que vai diretamente para grupos de linhas compactados. Qualquer dado que vá para um grupo de linhas delta é totalmente registrado. Isso inclui qualquer tamanho de lote com menos de 102.400 linhas. No entanto, com o carregamento em massa, o objetivo é que a maioria dos dados ignore os grupos de linhas delta.

    Otimização de bloqueio: ao carregar no grupo de linhas compactado, o bloqueio X no grupo de linhas é adquirido. No entanto, ao carregar em massa no grupo de linhas delta, um bloqueio X é adquirido no grupo de linhas, mas o SQL Server ainda bloqueia os bloqueios PAGE / EXTENT porque o bloqueio do grupo de linhas X não faz parte da hierarquia de bloqueio.

  17. A partir do SQL Server 2016, não é mais necessário habilitar o sinalizador de rastreamento 610 para o mínimo de log na tabela indexada . Citando o engenheiro da Microsoft Parikshit Savjani ( ênfase minha ):

    Um dos objetivos de design do SQL Server 2016 era melhorar o desempenho e a escalabilidade do mecanismo imediatamente para torná-lo mais rápido, sem a necessidade de botões ou sinalizadores de rastreamento para os clientes. Como parte desses aprimoramentos, um dos aprimoramentos feitos no código do mecanismo do SQL Server foi ativar o contexto de carregamento em massa (também conhecido como inserções rápidas ou contexto de carregamento rápido) e o registro mínimo por padrão ao executar operações de carregamento em massa no banco de dados com simples ou modelo de recuperação de log em massa. Se você não estiver familiarizado com o mínimo de log, eu recomendo a leitura desta postagem do blog da Sunil Agrawal, onde ele explica como o mínimo de log funciona no SQL Server. Para que as inserções em massa sejam minimamente registradas, ainda é necessário atender às condições pré-requisitos documentadas aqui.

    Como parte desses aprimoramentos no SQL Server 2016, não é mais necessário habilitar o sinalizador de rastreamento 610 para o mínimo de log na tabela indexadae une alguns dos outros sinalizadores de rastreamento (1118, 1117, 1236, 8048) para tornar-se parte da história. No SQL Server 2016, quando a operação de carregamento em massa faz com que uma nova página seja alocada, todas as linhas que preenchem sequencialmente essa nova página são minimamente registradas se todos os outros pré-requisitos para o mínimo de log discutidos anteriormente forem atendidos. As linhas inseridas nas páginas existentes (sem nova alocação de página) para manter a ordem do índice ainda são totalmente registradas, assim como as linhas movidas como resultado das divisões de página durante o carregamento. Também é importante ter ALLOW_PAGE_LOCKS ativado para índices (que está ativado por padrão) para que a operação mínima de registro funcione, pois os bloqueios de página são adquiridos durante a alocação e, portanto, apenas as alocações de página ou extensão são registradas.

  18. Se você estiver usando SqlBulkCopy em C # ou EntityFramework.Extensions (que usa SqlBulkCopy sob o capô), verifique sua configuração de compilação. Você está executando seus testes no modo Release? A arquitetura de destino está definida como Qualquer CPU / x64 / x86?

  19. Considere usar sp_who2 para ver se a transação INSERT BULK é SUSPENDED. Pode ser suspenso porque está bloqueado por outro spid. Considere ler Como minimizar o bloqueio do SQL Server . Você também pode usar o sp_WhoIsActive de Adam Machanic, mas o sp_who2 fornecerá as informações básicas necessárias.

  20. Você pode ter apenas E / S de disco defeituoso. Se você estiver fazendo uma inserção em massa e a utilização do disco não estiver atingindo 100% e estiver bloqueado em cerca de 2%, é provável que você tenha um firmware ruim ou um dispositivo de E / S com defeito. (Isso aconteceu com um colega de trabalho meu.) Use [SSD UserBenchmark] para comparar com outras pessoas o desempenho do hardware, especialmente se você pode replicar a lentidão na sua máquina de desenvolvimento local. (Coloquei isso por último na lista porque a maioria das empresas não permite que os desenvolvedores executem bancos de dados em suas máquinas locais devido ao risco de IP.)

  21. Se sua tabela usa compactação, você pode tentar executar várias sessões e, em cada sessão, comece usando uma transação existente e execute-a antes do comando SqlBulkCopy:

    ALTER SERVER CONFIGURAÇÃO CONFIGURAR PROCESSO AFINIDADE CPU = AUTO;

  22. Para carregamento contínuo, um fluxo de idéias, descrito primeiro no whitepaper da Microsoft, Tabela particionada e estratégias de índice usando o SQL Server 2008 :

    Carregamento contínuo

    Em um cenário OLTP, novos dados podem estar chegando continuamente. Se os usuários também estiverem consultando a partição mais recente, a inserção contínua de dados poderá levar ao bloqueio: as consultas do usuário podem bloquear as inserções e, da mesma forma, as inserções podem bloquear as consultas do usuário.

    A contenção na tabela ou partição de carregamento pode ser reduzida usando o isolamento de captura instantânea - em particular, o READ COMMITTED SNAPSHOTnível de isolamento. Sob READ COMMITTED SNAPSHOTisolamento, as inserções em uma tabela não causam atividade no repositório de versões do tempdb ; portanto, a sobrecarga do tempdb é mínima para inserções, mas nenhum bloqueio compartilhado será executado pelas consultas do usuário na mesma partição.

    Em outros casos, quando os dados estão sendo inseridos em uma tabela particionada continuamente a uma taxa alta, você ainda pode preparar os dados por curtos períodos de tempo nas tabelas temporárias e, em seguida, inserir esses dados na partição mais nova repetidamente até a janela de a partição atual passa e os dados são inseridos na próxima partição. Por exemplo, suponha que você tenha duas tabelas intermediárias que recebem 30 segundos de dados cada, em uma base alternativa: uma tabela para a primeira metade de um minuto, a segunda tabela para a segunda metade de um minuto. Um procedimento armazenado de inserção determina em que metade do minuto está a inserção atual e, em seguida, é inserido na primeira tabela de preparação. Quando 30 segundos terminam, o procedimento de inserção determina que ele deve ser inserido na segunda tabela de preparação. Outro procedimento armazenado carrega os dados da primeira tabela temporária na partição mais recente da tabela e, em seguida, trunca a primeira tabela temporária. Após outros 30 segundos, o mesmo procedimento armazenado insere os dados do segundo procedimento armazenado e os coloca na partição atual e, em seguida, trunca a segunda tabela de armazenamento temporário.

  23. Guia de desempenho para carregamento de dados da equipe Microsoft CAT

  24. Verifique se suas estatísticas estão atualizadas. Use FULLSCAN se possível após cada compilação de índice.

  25. SAN Performance Tuning com SQLIO e também verifique se você está usando discos mecânicos para alinhar suas partições de disco. Consulte Práticas recomendadas para alinhamento de partições de disco da Microsoft .

  26. COLUMNSTORE INSERT/ UPDATEperformance

John Zabroski
fonte
2

É provável que as leituras sejam as restrições únicas de & FK sendo verificadas durante a inserção - você pode obter uma melhoria de velocidade se puder desativá-las / eliminá-las durante a inserção e ativá-las / recriá-las posteriormente. Você precisará testar se isso o torna mais lento no geral, em comparação com a manutenção deles. Isso também pode não ser uma boa ideia se outros processos estiverem gravando na mesma tabela simultaneamente. - Gareth Lyons

De acordo com as perguntas e respostas, as chaves estrangeiras não são confiáveis ​​após a inserção em massa , as restrições FK não são confiáveis ​​após uma opção BULK INSERTsem CHECK_CONSTRAINTSopção (no meu caso, como encerrei com restrições não confiáveis). Não está claro, mas não faria sentido verificá-las e ainda torná-las não confiáveis. No entanto, PK e UNIQUE ainda serão verificados (consulte BULK INSERT (Transact-SQL) ). - Alexei

user126897
fonte