Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Inserção em Massa do SQL Server – Parte 2


Na parte anterior deste artigo, discutimos como importar arquivos CSV para o SQL Server com a ajuda da instrução BULK INSERT. Discutimos a principal metodologia do processo de inserção a granel e também os detalhes das opções BATCHSIZE e MAXERRORS nos cenários. Nesta parte, vamos passar por algumas outras opções (FIRE_TRIGGERS, CHECK_CONSTRAINTS e TABLOCK) do processo de inserção em massa em vários cenários.



Cenário 1:podemos habilitar acionadores na tabela de destino durante a operação de inserção em massa?

Por padrão, durante o processo de inserção em massa, os gatilhos de inserção especificados na tabela de destino não são acionados, no entanto, em algumas situações, podemos querer habilitar esses gatilhos. Uma solução para esse problema é usar a opção FIRE_TRIGGERS em instruções de inserção em massa. Quero adicionar um aviso de que essa opção pode afetar e diminuir o desempenho da operação de inserção em massa porque o gatilho/gatilhos podem fazer operações separadas no banco de dados. No exemplo a seguir, vamos demonstrar isso. A princípio, não definiremos o parâmetro FIRE_TRIGGERS e o processo de inserção em massa não acionará o acionador de inserção. No script T-SQL a seguir, definiremos um gatilho de inserção para a tabela Sales.
DROP TABLE IF EXISTS Sales CREATE TABLE [dbo].[Sales]( [Region] [varchar](50) , [Country] [varchar](50) , [ItemType] [varchar](50) NULL, [ SalesChannel] [varchar](50) NULL, [OrderPriority] [varchar](50) NULL, [OrderDate] datetime, [OrderID] bigint NULL, [ShipDate] datetime, [UnitsSold] float, [UnitPrice] float, [UnitCost] float, [TotalRevenue] float, [TotalCost] float, [TotalProfit] float) DROP TABLE IF EXISTS SalesLogCREATE TABLE SalesLog (OrderIDLog bigint)GOCREATE TRIGGER OrderLogIns ON SalesFOR INSERTASBEGIN SET NOCOUNT ON INSERT INTO SalesLogSELECT OrderId from insertendGOBULK INSERT SalesFROM 'C:\1500000 Registros de vendas.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n' ); SELECT Count(*) FROM SalesLog



Como você pode ver acima, o gatilho de inserção não disparou porque não configuramos a opção FIRE_TRIGGERS. Agora, adicionaremos a opção FIRE_TRIGGERS à instrução de inserção em massa para que essa opção permita inserir um gatilho de disparo.
BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n',FIRE_TRIGGERS);GOSELECT Count(*) as [NumberOfRowsinTriggerTable] FROM SalesLog  


Cenário 2:como ativar uma restrição de verificação durante a operação de inserção em massa?

As restrições de verificação nos permitem impor a integridade dos dados nas tabelas do SQL Server. O objetivo da restrição é verificar os valores inseridos, atualizados ou excluídos de acordo com sua regulação de sintaxe. Por exemplo, a restrição NOT NULL fornece que uma coluna especificada não pode ser modificada pelo valor NULL. Agora, vamos nos concentrar nas restrições e na interação de inserção em massa. Por padrão, durante o processo de inserção em massa, qualquer verificação e restrições de chave estrangeira são ignoradas, mas essa opção tem algumas exceções. De acordo com a documentação da Microsoft “as restrições UNIQUE e PRIMARY KEY são sempre aplicadas. Ao importar para uma coluna de caracteres  para a qual a restrição NOT NULL está definida, BULK INSERT insere uma string em branco quando não há valor no arquivo de texto." No script T-SQL a seguir, adicionaremos uma restrição de verificação à coluna OrderDate que controla a data do pedido maior que 01.01.2016.
DROP TABLE IF EXISTS Sales CREATE TABLE [dbo].[Sales]( [Region] [varchar](50) , [Country] [varchar](50) , [ItemType] [varchar](50) NULL, [ SalesChannel] [varchar](50) NULL, [OrderPriority] [varchar](50) NULL, [OrderDate] datetime, [OrderID] bigint NULL, [ShipDate] datetime, [UnitsSold] float, [UnitPrice] float, [UnitCost] float, [TotalRevenue] float, [TotalCost] float, [TotalProfit] float) ALTER TABLE [Sales] ADD CONSTRAINT OrderDate_CheckCHECK(OrderDate>'20160101')BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2 , FIELDTERMINATOR =',', ROWTERMINATOR='\n' );GOSELECT COUNT(*) AS [UnChekedData] FROM Sales WHERE OrderDate <'20160101'



Como você pode ver no exemplo acima, o processo de inserção em massa ignora o controle de restrição de verificação. No entanto, o SQL Server indica a restrição de verificação como não confiável.
SELECT is_not_trusted,* FROM sys.check_constraints where name='OrderDate_Check'



Este valor indica que alguém inseriu ou atualizou alguns dados nesta coluna ignorando a restrição de verificação, ao mesmo tempo que esta coluna pode conter dados inconsistentes com referência a essa restrição. Agora, tentaremos executar a instrução de inserção em massa com a opção CHECK_CONSTRAINTS. O resultado é muito simples, check constraint retorna um erro devido a dados impróprios.
BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n' );



Cenário 3:como aumentar o desempenho em várias inserções em massa em uma tabela de destino?

O principal objetivo do mecanismo de bloqueio no SQL Server é proteger e garantir a integridade dos dados. No artigo Conceito principal de bloqueio do SQL Server, você pode encontrar detalhes sobre o mecanismo de bloqueio. Agora, vamos nos concentrar nos detalhes de bloqueio do processo de inserção em massa. Se você executar a instrução de inserção em massa sem a opção TABLELOCK, ela adquirirá o bloqueio de linhas ou tabela de acordo com a hierarquia de bloqueio. No entanto, em alguns casos, podemos querer executar vários processos de inserção em massa em uma tabela de destino, para que possamos diminuir o tempo de operação da inserção em massa. Inicialmente, executaremos duas instruções de inserção em massa simultaneamente e analisaremos o comportamento do mecanismo de bloqueio. Abriremos duas janelas de consulta no SQL Server Management Studio e executaremos as seguintes instruções de inserção em massa simultaneamente.
BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n' );



Quando executamos a seguinte consulta dmv (Dynamic Management View), que ajuda a monitorar o status do processo de inserção em massa.
SELECT session_id,command ,status,last_wait_type,text FROM sys.dm_exec_requests cross apply sys.dm_exec_sql_text(sys.dm_exec_requests.sql_handle)onde texto como '%BULK INSERT Sales%' e session_id <>@@SPID



Como você pode ver na imagem acima, sessão 61, o status do processo de inserção em massa está suspenso devido ao bloqueio. Se verificarmos o problema, a sessão 59 bloqueia a tabela de destino de inserção em massa e a sessão 61 aguarda a liberação desse bloqueio para continuar o processo de inserção em massa. Agora, adicionaremos a opção TABLOCK às instruções de inserção em massa e executaremos as consultas.





Quando executamos a consulta de monitoramento dmv novamente, não vemos nenhum processo de inserção em massa suspenso porque o SQL Server usa um tipo de bloqueio especial  chamado bloqueio de atualização em massa (BU). Esse tipo de bloqueio permite processar várias operações de inserção em massa na mesma tabela simultaneamente e essa opção também diminui o tempo total do processo de inserção em massa.

Quando executamos a consulta a seguir durante o processo de inserção em massa, podemos monitorar os detalhes e os tipos de bloqueio.
SELECT dm_tran_locks.request_session_id, dm_tran_locks.resource_database_id, DB_NAME(dm_tran_locks.resource_database_id) AS dbname, CASE WHEN resource_type ='OBJECT' THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id_ID) ELSE OBJECT_NAME(partitions. indexes.name AS index_name, dm_tran_locks.resource_type, dm_tran_locks.resource_description, dm_tran_locks.resource_associated_entity_id, dm_tran_locks.request_mode, dm_tran_locks.request_statusFROM sys.dm_tran_locksLEFT JOIN sys.partitions ON partitions.hobt_id =dm_tran_locks.resource_associated_entity_idLEFT JOIN sys.indexes ON indexes.OBJECT_ID =partitions .OBJECT_ID AND indexes.index_id =partitions.index_idWHERE resource_associated_entity_id> 0 AND resource_database_id =DB_ID()



Conclusão

Neste artigo, exploramos todos os detalhes da operação de inserção em massa no SQL Server. Em particular, mencionamos o comando BULK INSERT e suas configurações e opções, e também analisamos vários cenários que se aproximam de problemas da vida real.

 

Referências


BULK INSERT (Transact-SQL)

Pré-requisitos para log mínimo na importação em massa

Controlando o comportamento de bloqueio para importação em massa

Leitura adicional


Exportando dados para arquivo simples com o utilitário BCP e importando dados com inserção em massa

Ferramenta útil:


dbForge Data Pump – um add-in SSMS para preencher bancos de dados SQL com dados de origem externa e migrar dados entre sistemas.