Поделиться через


Использование API массового копирования для операции пакетной вставки

Скачать драйвер JDBC

Microsoft JDBC Driver for SQL Server версии 9.2 и более поздних поддерживает использование интерфейса API массового копирования для пакетных операций вставки. Эта функция позволяет активировать в драйвере выполнение операции массового копирования при выполнении операций пакетной вставки. Драйвер позволяет повысить производительность вставки аналогичного объема данных по сравнению с обычной операцией пакетной вставки. Драйвер анализирует SQL-запрос пользователя, используя интерфейс API массового копирования вместо обычной операции пакетной вставки. Следующие параметры — это различные способы включения API массового копирования для функции пакетной вставки и перечисления ограничений. На этой странице также содержится небольшой пример кода, демонстрирующий использование и увеличение производительности.

Эта функция применима только к API-интерфейсам PreparedStatement и CallableStatement executeBatch() executeLargeBatch() .

Необходимые компоненты

Предварительные требования для включения интерфейса API для пакетной вставки.

  • Требуется запрос INSERT (запрос может содержать комментарии, но должен начинаться с ключевого слова INSERT, чтобы эта функция действовала).

Включение API массового копирования для операции пакетной вставки

Существует три способа включения API-интерфейса массового копирования для пакетной вставки.

1. Включение с помощью свойства подключения

Добавление useBulkCopyForBatchInsert=true; в строка подключения включает эту функцию.

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

2. Включение с помощью метода setUseBulkCopyForBatchInsert() из объекта SQLServerConnection

Эту функцию можно включить с помощью вызова SQLServerConnection.setUseBulkCopyForBatchInsert(true).

Вызов SQLServerConnection.getUseBulkCopyForBatchInsert() извлекает текущее значение свойства подключения useBulkCopyForBatchInsert.

Значение параметра useBulkCopyForBatchInsert остается постоянным для каждой инструкции PreparedStatement во время инициализации. Последующие вызовы SQLServerConnection.setUseBulkCopyForBatchInsert() не влияют на уже созданное значение PreparedStatement.

3. Включение с помощью метода setUseBulkCopyForBatchInsert() из объекта SQLServerDataSource

Аналогично предыдущему параметру, но при использовании SQLServerDataSource для создания объекта SQLServerConnection. Оба метода дают одинаковый результат.

Известные ограничения

В настоящее время к этой функции применяются следующие ограничения.

  • Запросы вставки, содержащие непараметризованные значения (например, INSERT INTO TABLE VALUES (?, 2), не поддерживаются. Подстановочные знаки (?) — единственные поддерживаемые параметры для этой функции.
  • Запросы вставки, содержащие выражения INSERT-SELECT (например, INSERT INTO TABLE SELECT * FROM TABLE2), не поддерживаются.
  • Запросы вставки, содержащие несколько выражений VALUE (например, INSERT INTO TABLE VALUES (1, 2) (3, 4)), не поддерживаются.
  • Запросы вставки, за которыми следует предложение OPTION, объединенное с несколькими таблицами, или за которыми следует другой запрос, не поддерживаются.
  • IDENTIY_INSERT не управляется в драйвере. Столбцы удостоверений не включаются в инструкции insert, вручную задают IDENTITY_INSERT состояние таблиц между операторами пакетной вставки или вручную передают явное значение столбца удостоверения с помощью инструкции insert. Дополнительные сведения см. в разделе SET IDENTITY_INSERT.
  • Из-за ограничений, связанных с API массового копирования, типы данных MONEY, SMALLMONEY, DATE, DATETIME, DATETIMEOFFSET, SMALLDATETIME, TIME, GEOMETRY и GEOGRAPHY в настоящее время не поддерживаются для этой функции.

Если запрос завершается ошибкой из-за ошибок, не связанных с экземпляром SQL Server, драйвер записывает сообщение об ошибке и возвращается к исходной логике для пакетной вставки.

Пример

В этом примере демонстрируется вариант использования для пакетной операции вставки тысяч строк как для обычных, так и для сценариев 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.");
        }
    }

Результат:

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.

См. также

Повышение производительности и надежности с помощью JDBC Driver