Menggunakan API salinan massal untuk operasi penyisipan batch

Unduh driver JDBC

Microsoft JDBC Driver untuk SQL Server versi 9.2 ke atas mendukung penggunaan API Salin Massal untuk operasi penyisipan batch. Fitur ini memungkinkan pengguna mengaktifkan agar driver melakukan operasi Bulk Copy secara internal saat menjalankan operasi batch insert. Driver bertujuan untuk mencapai peningkatan performa sambil menyisipkan data yang sama dengan yang akan dimiliki driver dengan operasi penyisipan batch reguler. Driver mengurai Kueri SQL pengguna, menggunakan API Salin Massal alih-alih operasi penyisipan batch biasa. Pengaturan berikut menyediakan berbagai cara untuk mengaktifkan API Bulk Copy bagi fitur penyisipan batch serta menjelaskan keterbatasannya. Halaman ini juga berisi kode sampel kecil yang menunjukkan penggunaan dan peningkatan performa juga.

Fitur ini hanya berlaku untuk executeBatch() & executeLargeBatch() API PreparedStatement dan CallableStatement.

Prasyarat

Persyaratan untuk mengaktifkan Bulk Copy API untuk penyisipan massal.

  • Kueri harus berupa kueri sisipkan (kueri mungkin berisi komentar, tetapi kueri harus dimulai dengan INSERT kata kunci agar fitur ini mulai berlaku).

Mengaktifkan API salinan massal untuk penyisipan batch

Ada tiga cara untuk mengaktifkan Bulk Copy API untuk penyisipan batch.

1. Mengaktifkan melalui properti koneksi

Menambahkan useBulkCopyForBatchInsert=true; ke string koneksi akan mengaktifkan fitur ini.

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

2. Mengaktifkan dengan metode setUseBulkCopyForBatchInsert() dari objek SQLServerConnection

Memanggil SQLServerConnection.setUseBulkCopyForBatchInsert(true) memungkinkan fitur ini.

SQLServerConnection.getUseBulkCopyForBatchInsert() mengambil nilai saat ini untuk properti koneksi useBulkCopyForBatchInsert .

Nilai untuk useBulkCopyForBatchInsert tetap konstan untuk setiap PreparedStatement pada saat inisialisasinya. Panggilan berikutnya ke SQLServerConnection.setUseBulkCopyForBatchInsert() tidak memengaruhi nilai PreparedStatement yang sudah dibuat.

3. Mengaktifkan dengan metode setUseBulkCopyForBatchInsert() dari objek SQLServerDataSource

Mirip dengan opsi sebelumnya, tetapi menggunakan SQLServerDataSource untuk membuat objek SQLServerConnection. Kedua metode mencapai hasil yang sama.

Pembatasan yang diketahui

Saat ini ada batasan yang berlaku untuk fitur ini.

  • Kueri insert yang berisi nilai yang tidak diparameterisasi (misalnya, INSERT INTO TABLE VALUES (?, 2)), tidak didukung. Kartubebas (?) adalah satu-satunya parameter yang didukung untuk fungsi ini.
  • Kueri INSERT yang berisi ekspresi INSERTSELECT (misalnya, INSERT INTO TABLE SELECT * FROM TABLE2) tidak didukung.
  • Sisipkan kueri yang berisi beberapa ekspresi VALUE (misalnya, INSERT INTO TABLE VALUES (1, 2) (3, 4)), tidak didukung.
  • Kueri INSERT yang diikuti oleh klausa OPTION, yang digabungkan dengan beberapa tabel, atau yang diikuti oleh kueri lain, tidak didukung.
  • IDENTITY_INSERT tidak dikelola di driver. Anda dapat tidak menyertakan kolom identity dalam pernyataan INSERT, mengatur secara manual status IDENTITY_INSERT tabel Anda di antara pernyataan INSERT batch, atau meneruskan secara manual nilai eksplisit untuk kolom identity dalam pernyataan INSERT. Untuk informasi selengkapnya, lihat SET IDENTITY_INSERT .
  • Karena keterbatasan Bulk Copy API, tipe data MONEY, SMALLMONEY, DATE, DATETIME, DATETIMEOFFSET, SMALLDATETIME, TIME, GEOMETRY, dan GEOGRAPHY saat ini tidak didukung untuk fitur ini pada Azure SQL DW.

Jika kueri gagal karena kesalahan yang tidak berkaitan dengan instans SQL Server, driver mencatat pesan kesalahan dan kembali menggunakan logika asli untuk penyisipan batch.

Contoh

Contoh ini menunjukkan kasus penggunaan untuk operasi batch insert sebanyak seribu baris, baik untuk skenario reguler maupun skenario Bulk Copy API.

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

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

        try (Connection con = DriverManager.getConnection(connectionUrl);
                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(connectionUrl + ";useBulkCopyForBatchInsert=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.");
        }
    }

Hasil:

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.