sql >> データベース >  >> RDS >> Sqlserver

SQL Server一括挿入–パート1

    ウィキペディアによると、「一括挿入は、データベーステーブルに複数行のデータをロードするためにデータベース管理システムによって提供されるプロセスまたはメソッドです。」この説明をBULKINSERTステートメントに従って調整すると、一括挿入により、外部データファイルをSQLServerにインポートできます。組織に1.500.000行のCSVファイルがあり、このファイルをSQL Serverの特定のテーブルにインポートして、SQLServerでBULKINSERTステートメントを簡単に使用できると仮定します。確かに、このCSVファイルのインポートプロセスを処理するためのいくつかのインポート方法を見つけることができます。 bcp( b )を使用できます ulk c opy p rogram)、SQLServerインポートおよびエクスポートウィザードまたはSQLServerIntegrationServiceパッケージ。ただし、BULK INSERTステートメントは、他の方法を使用するよりもはるかに高速で堅牢です。一括挿入ステートメントのもう1つの利点は、一括挿入プロセスの設定を決定するのに役立ついくつかのパラメーターを提供することです。

    最初に、非常に基本的なサンプルを開始し、次にさまざまな高度なシナリオを実行します。

    準備

    サンプルを開始する前に、サンプルのCSVファイルが必要です。そのため、E for ExcelのWebサイトからサンプルCSVファイルをダウンロードします。ここでは、行番号が異なるさまざまなサンプルCSVファイルを見つけることができます。リンクは記事の最後にあります。このシナリオでは、1.500.000の販売レコードを使用します。 zipファイルをダウンロードしてからCSVファイルを解凍し、ローカルドライブに配置します。

    CSVファイルをSQLServerテーブルにインポートする

    シナリオ-1:宛先ファイルとCSVファイルの列数は同じです

    この最初のシナリオでは、CSVファイルを最も単純な形式で宛先テーブルにインポートします。サンプルのCSVファイルをC:ドライブに配置し、CSVファイルからデータをインポートするテーブルを作成します。

    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
    )

    次のBULKINSERTステートメントは、CSVファイルをSalesテーブルにインポートします。

    BULK INSERT Sales
    FROM 'C:\1500000 Sales Records.csv'
    WITH (FIRSTROW = 2,
        FIELDTERMINATOR = ',',
    	ROWTERMINATOR='\n' );

    次に、上記の一括挿入ステートメントのパラメーターについて説明します。

    FIRSTROWパラメーターは、挿入ステートメントの開始点を指定します。次の例では、列ヘッダーをスキップするため、このパラメーターを2に設定します。

    FIELDTERMINATORは、フィールドを相互に分離する文字を定義します。 SQL Serverは、このような方法で各フィールドを検出します。 ROWTERMINATORはFIELDTERMINATORと大差ありません。行の分離文字を定義します。サンプルCSVファイルでは、fieldterminatorは非常に明確で、コンマ(、)です。しかし、どうすればフィールドターミネータを検出できますか? Notepad ++でCSVファイルを開き、[表示]->[記号を表示]->[すべてのチャーターを表示]に移動して、各フィールドの最後にあるCRLF文字を見つけます。

    CR=キャリッジリターンおよびLF=ラインフィード。これらは、テキストファイルの改行をマークするために使用され、一括挿入ステートメントでは「\n」文字で示されます。

    一括挿入を使用してCSVファイルをテーブルにインポートする別の方法は、FORMATパラメーターを使用することです。 FORMATパラメータはSQLServer2017以降のバージョンでのみ使用できることに注意してください。

    BULK INSERT Sales
    FROM 'C:\1500000 Sales Records.csv'
    WITH (FORMAT='CSV' , FIRSTROW = 2);

    次に、別のシナリオを分析します。

    シナリオ-2:宛先テーブルにCSVファイルよりも多くの列があります

    このシナリオでは、Salesテーブルに主キーを追加します。この場合、等式列のマッピングが壊れます。ここで、主キーを使用してSalesテーブルを作成し、一括挿入コマンドを使用してCSVファイルをインポートしようとすると、エラーが発生します。

    DROP TABLE IF EXISTS Sales 
    
    CREATE TABLE [dbo].[Sales](
        Id INT PRIMARY KEY IDENTITY (1,1),
    	[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
    ) 
    
    BULK INSERT Sales
    FROM 'C:\1500000 Sales Records.csv'
    WITH (FIRSTROW = 2,
        FIELDTERMINATOR = ',',
    	ROWTERMINATOR='\n' );

    このエラーを解決するために、列をCSVファイルにマッピングするSalesテーブルのビューを作成し、このビューを介してCSVデータをSalesテーブルにインポートします。

    DROP VIEW IF EXISTS VSales 
    GO
    CREATE VIEW VSales
    AS
    SELECT Region ,
    Country ,
    ItemType ,
    SalesChannel , 
    OrderPriority ,
    OrderDate , 
    OrderID ,
    ShipDate ,
    UnitsSold , 
    UnitPrice ,
    UnitCost ,
    TotalRevenue,
    TotalCost, 
    TotalProfit from Sales
    
    GO 
    
    BULK INSERT VSales
    FROM 'C:\1500000 Sales Records.csv'
    WITH ( FIRSTROW = 2,
           FIELDTERMINATOR = ',',
    	ROWTERMINATOR='\n' );

    シナリオ-3:CSVファイルを分離して小さなバッチサイズにロードする方法

    SQL Serverは、一括挿入操作中に宛先テーブルへのロックを取得します。既定では、BATCHSIZEパラメータを設定しない場合、SQL Serverはトランザクションを開き、CSVデータ全体をこのトランザクションに挿入します。ただし、BATCHSIZEパラメーターを設定すると、SQLServerはこのパラメーター値に従ってCSVデータを分割します。次のサンプルでは、​​CSVデータ全体をそれぞれ300.000行のいくつかのセットに分割します。したがって、データは5回インポートされます。

    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
    ) 
    
    
    BULK INSERT Sales
    FROM 'C:\1500000 Sales Records.csv'
    WITH (FIRSTROW = 2,
        FIELDTERMINATOR = ',',
    	ROWTERMINATOR='\n' ,
    	batchsize=300000 );

    一括挿入ステートメントにバッチサイズ(BATCHSIZE)パラメーターが含まれていない場合、エラーが発生し、SQLServerは一括挿入プロセス全体をロールバックします。一方、バッチサイズパラメータを一括挿入ステートメントに設定すると、SQL Serverは、エラーが発生したこの分割された部分のみをロールバックします。このパラメータ値はデータベースシステム要件に応じて変更できるため、このパラメータの最適値または最適値はありません。

    シナリオ-4:キャンセルする方法 エラーが発生したときにプロセスをインポートしますか?

    一部の一括コピーのシナリオでは、エラーが発生した場合、一括コピープロセスをキャンセルするか、プロセスを続行する必要があります。 MAXERRORSパラメーターを使用すると、エラーの最大数を指定できます。一括挿入プロセスがこの最大エラー値に達すると、一括インポート操作はキャンセルされ、ロールバックされます。このパラメータのデフォルト値は10です。

    次の例では、CSVファイルの3行のデータ型を意図的に破損し、MAXERRORSパラメータを2に設定します。その結果、エラー数が最大エラーパラメータを超えたため、一括挿入操作全体がキャンセルされます。

    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,
    	[Order Date]  datetime,
    	[OrderID] bigint NULL,
    	[ShipDate] datetime,
    	[UnitsSold]  float,
    	[UnitPrice] float,
    	[UnitCost] float,
    	[TotalRevenue] float,
    	[TotalCost]  float,
    	[TotalProfit] float
    ) 
    
    BULK INSERT Sales
    FROM 'C:\1500000 Sales Records.csv'
    WITH (FIRSTROW = 2,
        FIELDTERMINATOR = ',',
    	ROWTERMINATOR='\n' ,
    	 MAXERRORS=2);

    ここで、max errorパラメーターを4に変更します。その結果、一括挿入ステートメントはこれらの行をスキップして適切なデータ構造化行を挿入し、一括挿入プロセスを完了します。

    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,
    	[Order Date]  datetime,
    	[OrderID] bigint NULL,
    	[ShipDate] datetime,
    	[UnitsSold]  float,
    	[UnitPrice] float,
    	[UnitCost] float,
    	[TotalRevenue] float,
    	[TotalCost]  float,
    	[TotalProfit] float
    ) 
    BULK INSERT Sales
    FROM 'C:\1500000 Sales Records.csv'
    WITH (FIRSTROW = 2,
        FIELDTERMINATOR = ',',
    	ROWTERMINATOR='\n' ,
    	 MAXERRORS=4);
    	 
    	 
    	 
    SELECT COUNT(*) AS [NumberofImportedRow] FROM 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,
    	[Order Date]  datetime,
    	[OrderID] bigint NULL,
    	[ShipDate] datetime,
    	[UnitsSold]  float,
    	[UnitPrice] float,
    	[UnitCost] float,
    	[TotalRevenue] float,
    	[TotalCost]  float,
    	[TotalProfit] float
    ) 
    BULK INSERT Sales
    FROM 'C:\1500000 Sales Records.csv'
    WITH (FIRSTROW = 2,
        FIELDTERMINATOR = ',',
    	ROWTERMINATOR='\n' ,
    	 MAXERRORS=2,
    BATCHSIZE=750000);
    GO 
    SELECT COUNT(*) AS [NumberofImportedRow] FROM Sales

    この一連の記事の最初のパートでは、SQL Serverで一括挿入操作を使用する基本について説明し、実際の問題に近いいくつかのシナリオを分析しました。

    SQL Server一括挿入–パート2

    便利なリンク:

    一括挿入

    E for Excel –テスト用のサンプルCSVファイル/データセット(150万レコードまで)

    Notepad++のダウンロード

    便利なツール:

    dbForge Data Pump – SQLデータベースに外部ソースデータを入力し、システム間でデータを移行するためのSSMSアドイン。


    1. MySQLでスラッシュ(\)を検索する方法は?そして、なぜエスケープ(\)は、where(=)ではなく、Likeが必要なのですか?

    2. setFetchSize()をいつ何を指定する必要がありますか?

    3. パラメータ化されたクエリが、パラメータ化されていないクエリと比較して非常に遅いクエリプランを生成するのはなぜですか

    4. MySQLでスペースを含む列名を選択する方法