I föregående del av den här artikeln diskuterade vi hur man importerar CSV-filer till SQL Server med hjälp av BULK INSERT-satsen. Vi diskuterade den huvudsakliga metoden för bulkinsertprocess och även detaljerna om BATCHSIZE och MAXERRORS alternativ i scenarier. I den här delen kommer vi att gå igenom några andra alternativ (FIRE_TRIGGERS, CHECK_CONSTRAINTS och TABLOCK) för massinsättningsprocessen i olika scenarier.
Scenario 1:Kan vi aktivera utlösare i destinationstabellen under massinsättningen?
Som standard, under massinsättningsprocessen, aktiveras inte infogningstriggarna som anges i måltabellen, men i vissa situationer kanske vi vill aktivera dessa triggers. En lösning på det här problemet är att använda FIRE_TRIGGERS-alternativet i massinsättningssatser. Jag vill lägga till ett meddelande om att det här alternativet kan påverka och minska prestandan för bulkinsertoperationen eftersom trigger/triggers kan göra separata operationer i databasen. I följande exempel kommer vi att visa detta. Till en början kommer vi inte att ställa in parametern FIRE_TRIGGERS och massinsättningsprocessen kommer inte att aktivera utlösaren för infogning. I följande T-SQL-skript kommer vi att definiera en infogningstrigger för försäljningstabellen.
SLÄPP TABELL OM FINNS Försäljning SKAPA TABELL [dbo].[Försäljning]( [Region] [varchar](50) , [Land] [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 FINNS SalesLogCREATE TABLE SalesLog (OrderIDLog bigint)GOCREATE TRIGGER OrderLogIns ON SalesFOR INSERTASBEGIN SET INCOUNT ON SalesLogINSERTTO SLÄGG IN0SÄLJER0CREATE INCOUNT ON Sales0INSERT10CREATE INCOUNT ON Sales0INSERT0 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n' ); VÄLJ Antal(*) FRÅN Försäljningslogg
Som du kan se ovan aktiverades inte insättningsutlösaren eftersom vi inte ställde in alternativet FIRE_TRIGGERS. Nu kommer vi att lägga till alternativet FIRE_TRIGGERS till bulkinsert-satsen så att det här alternativet gör det möjligt att infoga en brandutlösare.
BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n',FIRE_TRIGGERS);GOSELECT Räkna(*) som [NumberOfRowsinTriggerTable] /pre>
Scenario 2:Hur kan en kontrollbegränsning aktiveras under massinsättningen?
Kontrollbegränsningar tillåter oss att upprätthålla dataintegritet i SQL Server-tabeller. Syftet med begränsningen är att kontrollera infogade, uppdaterade eller raderade värden enligt deras syntaxreglering. Som t.ex. NOT NULL-begränsningen ger att en specificerad kolumn inte kan modifieras av NULL-värdet. Nu kommer vi att fokusera på begränsningar och interaktion med bulkinsert. Som standard ignoreras alla kontroll- och främmande nyckelbegränsningar under massinsättningsprocessen, men det här alternativet har några undantag. Enligt Microsofts dokumentation "UNIKA och PRIMARY KEY-begränsningar upprätthålls alltid. Vid import till en teckenkolumn för vilken NOT NULL-begränsningen är definierad, infogar BULK INSERT en tom sträng när det inte finns något värde i textfilen.” I följande T-SQL-skript kommer vi att lägga till en kontrollbegränsning i kolumnen OrderDate som styr orderdatumet större än 01.01.2016.
SLÄPP TABELL OM FINNS Försäljning SKAPA TABELL [dbo].[Försäljning]( [Region] [varchar](50) , [Land] [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 [Försäljning] ADD CONSTRAINT OrderDate_CheckCHECK(OrderDate>'20160101')BULK INSERT SalesFROM 'C:\1500000 Sales Records (FIRSsv'WWITH) , FIELDTERMINATOR =',', ROWTERMINATOR='\n' );GOSELECT COUNT(*) SOM [UnChekedData] FRÅN Sales WHERE OrderDate <'20160101'
Som du kan se i exemplet ovan hoppar massinsättningsprocessen över kontrollbegränsningskontrollen. SQL Server indikerar dock att kontrollbegränsningen inte är betrodd.
SELECT is_not_trusted ,* FROM sys.check_constraints där name='OrderDate_Check'
Detta värde indikerar att någon infogat eller uppdaterat vissa data till den här kolumnen genom att hoppa över kontrollbegränsningen, samtidigt som den här kolumnen kan innehålla inkonsekventa data med hänvisning till den begränsningen. Nu kommer vi att försöka köra bulk insert-satsen med alternativet CHECK_CONSTRAINTS. Resultatet är mycket enkelt, check constraint returnerar ett fel på grund av felaktig data.
BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n' );
Scenario 3:Hur ökar man prestandan i flera massinlägg i en måltabell?
Huvudsyftet med låsmekanismen i SQL Server är att skydda och säkerställa dataintegriteten. I huvudkonceptet för SQL Server-låsningsartikeln kan du hitta information om låsmekanismen. Nu kommer vi att fokusera på låsdetaljer för bulkinsertprocessen. Om du kör bulk insert-satsen utan TABLELOCK-alternativet, förvärvar den låsningen av rader eller tabell enligt låshierarkin. Men i vissa fall kanske vi vill köra flera massinsättningsprocesser mot en destinationstabell, så att vi kan minska driftstiden för massinsättningen. Till en början kommer vi att köra två bulkinsert-satser samtidigt och analysera låsmekanismens beteende. Vi kommer att öppna två frågefönster i SQL Server Management Studio och köra följande bulkinsert-satser samtidigt.
BULK INSERT SalesFROM 'C:\1500000 Sales Records.csv'WITH (FIRSTROW =2, FIELDTERMINATOR =',', ROWTERMINATOR='\n' );
När vi kör följande dmv-fråga (Dynamic Management View), som hjälper till att övervaka statusen för massinsättningsprocessen.
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)där text som '%BULK INSERT Sales%' och session_id@SP>
Som du kan se i bilden ovan, session 61, är bulkinsertprocessens status avstängd på grund av låsning. Om vi verifierar problemet låser session 59 destinationstabellen för massinsättning och session 61 väntar på att detta lås släpps för att fortsätta massinsättningsprocessen. Nu kommer vi att lägga till alternativet TABLOCK till bulkinsert-satserna och köra frågorna.
När vi kör dmv-övervakningsfrågan igen kan vi inte se någon avstängd massinsättningsprocess eftersom SQL Server använder en speciell låstyp kallad bulkuppdateringslås (BU). Den här låstypen gör det möjligt att behandla flera massinsättningsoperationer mot samma tabell samtidigt och detta alternativ minskar också den totala tiden för massinsättningsprocessen.
När vi utför följande fråga under massinsättningsprocessen kan vi övervaka låsdetaljerna och låstyperna.
VÄLJ 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' SEDAN OBJECT_NAME(dm_tran_partitions_locks.OBJECT_NAME)(dm_tran_partitions_locks.OBJECT_NAME_partitions.OBJECT_NAMN_partitions.partitions.OBJECT_NAME) 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()
Slutsats
I den här artikeln undersökte vi alla detaljer om bulkinfogning i SQL Server. Vi nämnde särskilt BULK INSERT-kommandot och dess inställningar och alternativ, och vi analyserade också olika scenarier som är nära verkliga problem.
Referenser
BULK INSERT (Transact-SQL)
Förutsättningar för minimal inloggning i massimport
Kontrollera låsbeteende för massimport
Ytterligare läsning
Exportera data till platt fil med BCP Utility och importera data med Bulk Insert
Användbart verktyg:
dbForge Data Pump – ett SSMS-tillägg för att fylla SQL-databaser med externa källdata och migrera data mellan system.