バッチ挿入操作に一括コピー API を使用するUsing bulk copy API for batch insert operation

ダウンロードJDBC Driver のダウンロードDownloadDownload JDBC Driver

Microsoft JDBC Driver 7.0 for SQL Server では、Azure Data Warehouse に対するバッチ挿入操作に一括コピー API の使用がサポートされています。Microsoft JDBC Driver 7.0 for SQL Server supports using Bulk Copy API for batch insert operations for Azure Data Warehouse. この機能を使用すると、ユーザーは、バッチ挿入操作の実行時に、一括コピー操作をドライバーにバックグラウンドで実行させることができるようになります。This feature allows users to enable driver to perform Bulk Copy operation underneath when executing batch insert operations. このドライバーは、通常のバッチ挿入操作で行われるのと同じデータを挿入したときのパフォーマンスを向上させることを目的としています。The driver aims to achieve improvement in performance while inserting the same data as the driver would have with regular batch insert operation. ドライバーでは、通常のバッチ挿入操作の代わりに、一括コピー API を利用して、ユーザーの SQL クエリが解析されます。The driver parses the user's SQL Query, leveraging the Bulk Copy API in lieu of the usual batch insert operation. バッチ挿入機能に対して一括コピー API を有効にするためのさまざまな方法と、その制限事項の一覧を以下に示します。Below are various ways to enable the Bulk Copy API for batch insert feature, as well as the list of its limitations. このページには、使用とパフォーマンスの向上を示す小さなサンプル コードも含まれています。This page also contains a small sample code that demonstrates a usage and the performance increase as well.

この機能は、PreparedStatement および CallableStatement の executeBatch() & executeLargeBatch() API にのみ適用できます。This feature is only applicable to PreparedStatement and CallableStatement's executeBatch() & executeLargeBatch() APIs.

前提条件Prerequisites

バッチ挿入に一括コピー API を有効にするには、次の 2 つの前提条件があります。There are two prerequisites to enable Bulk Copy API for batch insert.

  • サーバーは Azure Data Warehouse であること。The server must be Azure Data Warehouse.
  • クエリは挿入クエリであること (クエリにコメントを含めることはできますが、この機能を有効にするには、クエリの先頭に INSERT キーワードを使用する必要があります)。The query must be an insert query (the query may contain comments, but the query must start with the INSERT keyword for this feature to come into effect).

バッチ挿入に一括コピー API を有効にするEnabling bulk copy API for batch insert

バッチ挿入に一括コピー API を有効にするには、次の 3 つの方法があります。There are three ways to enable Bulk Copy API for batch insert.

1.接続プロパティを使用して有効にする1. Enabling with connection property

接続文字列に useBulkCopyForBatchInsert=true; を追加して、この機能を有効にします。Adding useBulkCopyForBatchInsert=true; to the connection string enables this feature.

Connection connection = DriverManager.getConnection("jdbc:sqlserver://<server>:<port>;userName=<user>;password=<password>;database=<database>;useBulkCopyForBatchInsert=true;");

2.SQLServerConnection オブジェクトから setUseBulkCopyForBatchInsert() メソッドを使用して有効にする2. Enabling with setUseBulkCopyForBatchInsert() method from SQLServerConnection object

SQLServerConnection.setUseBulkCopyForBatchInsert(true) を呼び出してこの機能を有効にします。Calling SQLServerConnection.setUseBulkCopyForBatchInsert(true) enables this feature.

SQLServerConnection.getUseBulkCopyForBatchInsert()useBulkCopyForBatchInsert 接続プロパティの現在の値が取得されます。SQLServerConnection.getUseBulkCopyForBatchInsert() retrieves the current value for useBulkCopyForBatchInsert connection property.

useBulkCopyForBatchInsert の値は、初期化時には各 PreparedStatement に対して一定のままです。The value for useBulkCopyForBatchInsert stays constant for each PreparedStatement at the time of its initialization. 後続の SQLServerConnection.setUseBulkCopyForBatchInsert() への呼び出しは、その値に関して、既に作成された PreparedStatement には影響しません。Any subsequent calls to SQLServerConnection.setUseBulkCopyForBatchInsert() will not affect the already created PreparedStatement with regard to its value.

3.SQLServerDataSource オブジェクトから setUseBulkCopyForBatchInsert() メソッドを使用して有効にする3. Enabling with setUseBulkCopyForBatchInsert() method from SQLServerDataSource object

上記と同様ですが、SQLServerDataSource を使用して SQLServerConnection オブジェクトを作成します。Similar to above, but using SQLServerDataSource to create a SQLServerConnection object. どちらの方法も、同じ結果が得られます。Both methods achieve the same result.

既知の制限事項Known limitations

現在、この機能には、次の制限事項が適用されます。There are currently these limitations that apply to this feature.

  • パラメーター化されていない値 (INSERT INTO TABLE VALUES (?, 2) など) を含む挿入クエリはサポートされていません。Insert queries that contain non-parameterized values (for example, INSERT INTO TABLE VALUES (?, 2)), are not supported. この関数でサポートされているパラメーターは、ワイルドカード (?) だけです。Wildcards (?) are the only supported parameters for this function.
  • INSERT-SELECT 式 (INSERT INTO TABLE SELECT * FROM TABLE2 など) を含む挿入クエリはサポートされていません。Insert queries that contain INSERT-SELECT expressions (for example, INSERT INTO TABLE SELECT * FROM TABLE2), are not supported.
  • 複数の VALUE 式 (INSERT INTO TABLE VALUES (1, 2) (3, 4) など) を含む挿入クエリはサポートされていません。Insert queries that contain multiple VALUE expressions (for example, INSERT INTO TABLE VALUES (1, 2) (3, 4)), are not supported.
  • OPTION 句が後に続く挿入クエリ、複数のテーブルと結合された挿入クエリ、または別のクエリが後に続く挿入クエリはサポートされていません。Insert queries that are followed by the OPTION clause, joined with multiple tables, or followed by another query, are not supported.
  • 一括コピー API の制限により、MONEYSMALLMONEYDATEDATETIMEDATETIMEOFFSETSMALLDATETIMETIMEGEOMETRYGEOGRAPHY の各データ型は、現在、この機能ではサポートされていません。Due to the limitations of Bulk Copy API, MONEY, SMALLMONEY, DATE, DATETIME, DATETIMEOFFSET, SMALLDATETIME, TIME, GEOMETRY, and GEOGRAPHY data types, are currently not supported for this feature.

"SQL Server" に関連しないエラーが原因でクエリが失敗した場合、ドライバーによってエラー メッセージがログに記録され、バッチ挿入の元のロジックにフォールバックされます。If the query fails because of non "SQL server" related errors, the driver will log the error message and fallback to the original logic for batch insert.

Example

次に示すのは、通常と一括コピー API の両方のシナリオで、1000 行の Azure DW に対するバッチ挿入操作のユース ケースを示すコード例です。Below is an example code that demonstrates the use case for a batch insert operation against Azure DW of a thousand rows, for both (regular vs Bulk Copy API) scenarios.

    public static void main(String[] args) throws Exception
    {
        String tableName = "batchTest";
        String tableNameBulkCopyAPI = "batchTestBulk";

        String azureDWconnectionUrl = "jdbc:sqlserver://<server>:<port>;databaseName=<database>;user=<user>;password=<password>";

        try (Connection con = DriverManager.getConnection(azureDWconnectionUrl); // connects to an Azure Data Warehouse.
                Statement stmt = con.createStatement();
                PreparedStatement pstmt = con.prepareStatement("insert into " + tableName + " values (?, ?)");) {

            String dropSql = "if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[" + tableName + "]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) DROP TABLE [" + tableName + "]";
            stmt.execute(dropSql);

            String createSql = "create table " + tableName + " (c1 int, c2 varchar(20))";
            stmt.execute(createSql);

            System.out.println("Starting batch operation using regular batch insert operation.");
            long start = System.currentTimeMillis();
            for (int i = 0; i < 1000; i++) {
                pstmt.setInt(1, i);
                pstmt.setString(2, "test" + i);
                pstmt.addBatch();
            }
            pstmt.executeBatch();

            long end = System.currentTimeMillis();

            System.out.println("Finished. Time taken : " + (end - start) + " milliseconds.");
        }

        try (Connection con = DriverManager.getConnection(azureDWconnectionUrl + ";useBulkCopyForBatchInsert=true"); // connects to an Azure Data Warehouse, with useBulkCopyForBatchInsert connection property set to true.
                Statement stmt = con.createStatement();
                PreparedStatement pstmt = con.prepareStatement("insert into " + tableNameBulkCopyAPI + " values (?, ?)");) {

            String dropSql = "if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[" + tableNameBulkCopyAPI + "]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) DROP TABLE [" + tableNameBulkCopyAPI + "]";
            stmt.execute(dropSql);

            String createSql = "create table " + tableNameBulkCopyAPI + " (c1 int, c2 varchar(20))";
            stmt.execute(createSql);

            System.out.println("Starting batch operation using Bulk Copy API.");
            long start = System.currentTimeMillis();
            for (int i = 0; i < 1000; i++) {
                pstmt.setInt(1, i);
                pstmt.setString(2, "test" + i);
                pstmt.addBatch();
            }
            pstmt.executeBatch();

            long end = System.currentTimeMillis();

            System.out.println("Finished. Time taken : " + (end - start) + " milliseconds.");
        }
    }

結果:Result:

Starting batch operation using regular batch insert operation.
Finished. Time taken : 104132 milliseconds.
Starting batch operation using Bulk Copy API.
Finished. Time taken : 1058 milliseconds.

関連項目See also

JDBC ドライバーによるパフォーマンスと信頼性の強化Improving performance and reliability with the JDBC driver