В предишната част на тази статия обсъдихме как да импортирате CSV файлове в SQL Server с помощта на оператора BULK INSERT. Обсъдихме основната методология на процеса на групово вмъкване, както и подробностите за опциите BATCHSIZE и MAXERRORS в сценариите. В тази част ще преминем през някои други опции (FIRE_TRIGGERS, CHECK_CONSTRAINTS и TABLOCK) за процес на групово вмъкване в различни сценарии.
Сценарий 1:Можем ли да активираме задействания в целевата таблица по време на операцията за групово вмъкване?
По подразбиране, по време на процеса на групово вмъкване, тригерите за вмъкване, които са посочени в целевата таблица, не се задействат, но в някои ситуации може да искаме да активираме тези тригери. Решение на този проблем е да използвате опцията FIRE_TRIGGERS в изрази за групово вмъкване. Искам да добавя известие, че тази опция може да повлияе и да намали производителността на операцията за групово вмъкване, тъй като тригерите/тригерите могат да извършват отделни операции в базата данни. В следващата извадка ще демонстрираме това. Първо, ние няма да зададем параметъра FIRE_TRIGGERS и процесът на групово вмъкване няма да задейства тригера за вмъкване. В следващия T-SQL скрипт ще дефинираме тригер за вмъкване за таблицата Sales.
ПРОСТЪПНЕТЕ ТАБЛИЦА, АКО СЪЩЕСТВУВА Продажби СЪЗДАДЕТЕ ТАБЛИЦА [dbo].[Продажби]( [Регион] [varchar](50) , [Държава] [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], [UnitChannel float, [TotalRevenue] float, [TotalCost] float, [TotalProfit] float) DROP ТАБЛИЦА, АКО СЪЩЕСТВУВА SalesLogCREATE TABLE SalesLog (OrderIDLog bigint)GOCREATE TRIGGER OrderLogIns ON SalesFOR SAlesFOR INSERTNORTGOSELES INSERTNORTG0BENC INSERTNORTG0BGNES INSERTNORTG0BGNLS INSERTNO SELECT 0 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n'); ИЗБЕРЕТЕ Count(*) ОТ SalesLog
Както можете да видите по-горе, тригерът за вмъкване не се задейства, защото не сме задали опцията FIRE_TRIGGERS. Сега ще добавим опцията FIRE_TRIGGERS към израза за групово вмъкване, така че тази опция да даде възможност за вмъкване на задействане на пожар.
BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n',FIRE_TRIGGERS);GOSELECT Брой(*) като [NumberTLable]FROMTrigger /предварително>
Сценарий 2:Как може да се активира ограничение за проверка по време на операцията за групово вмъкване?
Ограниченията за проверка ни позволяват да наложим целостта на данните в таблиците на SQL Server. Целта на ограничението е да провери вмъкнати, актуализирани или изтрити стойности в съответствие с тяхното регулиране на синтаксиса. Като например, ограничението NOT NULL осигурява, че определена колона не може да бъде променена от стойността NULL. Сега ще се съсредоточим върху ограниченията и взаимодействието на групово вмъкване. По подразбиране по време на процеса на групово вмъкване всяка проверка и ограничения на външния ключ се игнорират, но тази опция има някои изключения. Според документацията на Microsoft „Ограниченията за УНИКАЛЕН и ПЪРВИЧЕН КЛЮЧ винаги се прилагат. При импортиране в символна колона за която е дефинирано ограничението NOT NULL, BULK INSERT вмъква празен низ, когато в текстовия файл няма стойност.“ В следващия T-SQL скрипт ще добавим ограничение за проверка към колоната OrderDate, която контролира датата на поръчката, по-голяма от 01.01.2016 г.
ПРОСТЪПНЕТЕ ТАБЛИЦА, АКО СЪЩЕСТВУВА Продажби СЪЗДАДЕТЕ ТАБЛИЦА [dbo].[Продажби]( [Регион] [varchar](50) , [Държава] [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], [UnitChannel float, [TotalRevenue] float, [TotalCost] float, [TotalProfit] float) ALTER TABLE [Продажби] ДОБАВЯНЕ НА ОГРАНИЧЕНИЕ OrderDate_CheckCHECK(OrderDate>'20160101')BULK INSERT SalesFROM 'C:\15 SalesFROM 'C:\15 SalesFROM 'C:\15 Sales'0 , FIELDTERMINATOR =',', ROWTERMINATOR='\n' );GOSELECT COUNT(*) КАТО [UnChekedData] FROM Sales WHERE OrderDate <'20160101'
Както можете да видите в горната проба, процесът на групово вмъкване пропуска контрола на ограничението за проверка. Въпреки това, SQL Server показва ограничението за проверка като недоверено.
SELECT is_not_trusted ,* FROM sys.check_constraints където name='OrderDate_Check'
Тази стойност показва, че някой е вмъкнал или актуализирал някои данни в тази колона, като е пропуснал ограничението за проверка, като в същото време тази колона може да съдържа непоследователни данни по отношение на това ограничение. Сега ще се опитаме да изпълним израза за групово вмъкване с опцията CHECK_CONSTRAINTS. Резултатът е много прост, ограничението за проверка връща грешка поради неправилни данни.
МАСНО ВМЕСТЕ SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n');
Сценарий 3:Как да повишите производителността при множество групови вмъквания в една целева таблица?
Основната цел на механизма за заключване в SQL Server е да защитава и гарантира целостта на данните. В статията Основна концепция за заключване на SQL Server можете да намерите подробности за механизма за заключване. Сега ще се съсредоточим върху детайлите за заключване на процеса на групово вмъкване. Ако изпълните израза за групово вмъкване без опцията TABLELOCK, той придобива заключването на редове или таблица според йерархията на заключване. Въпреки това, в някои случаи може да искаме да изпълним множество процеси на групово вмъкване срещу една целева таблица, така че можем да намалим времето за работа на груповото вмъкване. Първо ще изпълним едновременно два оператора за групово вмъкване и ще анализираме поведението на заключващия механизъм. Ще отворим два прозореца за заявка в SQL Server Management Studio и ще изпълним следните изрази за групово вмъкване едновременно.
МАСНО ВМЕСТЕ SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n');
Когато изпълним следната заявка dmv (Dynamic Management View), която помага да се наблюдава състоянието на процеса на групово вмъкване.
ИЗБЕРЕТЕ session_id,command ,status,last_wait_type,text FROM sys.dm_exec_requests кръстосано прилагане sys.dm_exec_sql_text(sys.dm_exec_requests.sql_handle) където текст като „%BULK INSERT Sales%@“@SP session_id <>>
Както можете да видите на горното изображение, сесия 61, състоянието на процеса на групово вмъкване е спряно поради заключване. Ако потвърдим проблема, сесия 59 заключва дестинационната таблица за групово вмъкване и сесия 61 изчаква освобождаването на това заключване, за да продължи процеса на групово вмъкване. Сега ще добавим опцията TABLOCK към изразите за групово вмъкване и ще изпълним заявките.
Когато изпълним отново заявката за наблюдение на dmv, не можем да видим никакъв спрян процес на групово вмъкване, тъй като SQL Server използва специален тип заключване, наречен заключване на групово актуализиране (BU). Този тип заключване позволява едновременното обработване на множество операции за групово вмъкване срещу една и съща таблица и тази опция също така намалява общото време на процеса на групово вмъкване.
Когато изпълним следната заявка по време на процеса на групово вмъкване, можем да наблюдаваме подробностите за заключване и типовете заключване.
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) ELSE OBJECT_NAME(partitions.OBJECT_ID) END AS ObjectName, partitions.index_id, 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 И indexes.index_id =partitions.index_idWHERE resource_associated_entity_id> 0 AND resource_database_id =DB_ID()
Заключение
В тази статия проучихме всички подробности за операцията за групово вмъкване в SQL Server. По-специално, споменахме командата BULK INSERT и нейните настройки и опции, а също така анализирахме различни сценарии, които са близки до проблемите в реалния живот.
Препратки
ОБЕТО ВМЕСВАНЕ (Transact-SQL)
Предпоставки за минимално регистриране при групов импорт
Контролиране на поведението на заключване при групов импорт
Допълнително четене
Експортиране на данни в плосък файл с помощта на BCP и импортиране на данни с групово вмъкване
Полезен инструмент:
dbForge Data Pump – SSMS добавка за попълване на SQL бази данни с външни изходни данни и мигриране на данни между системите.