Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Microsoft JDBC Driver for SQL Server версии 9.2 и выше поддерживает использование Bulk Copy API для операций пакетной вставки. Эта функция позволяет пользователям включить использование драйвером операций Bulk Copy на внутреннем уровне при пакетной вставке. Драйвер предназначен для повышения производительности при вставке тех же данных, что и при обычной операции пакетной вставки. Драйвер анализирует SQL-запрос пользователя, используя интерфейс API массового копирования вместо обычной операции пакетной вставки. Следующие настройки позволяют различными способами включить API массового копирования для функции пакетной вставки, а также перечисляют её ограничения. На этой странице также содержится небольшой пример кода, демонстрирующий использование и увеличение производительности.
Эта функция применима только к API-интерфейсам PreparedStatement и CallableStatement executeBatch()executeLargeBatch() .
Предварительные требования
Предварительное условие для включения Bulk Copy API для пакетной вставки.
- Запрос должен быть запросом вставки (запрос может содержать примечания, но запрос должен начинаться с INSERT ключевого слова, чтобы эта функция вступила в силу).
Включение API массового копирования для операции пакетной вставки
Существует три способа включить Bulk Copy 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, содержащие выражения INSERT-SELECT (например,
INSERT INTO TABLE SELECT * FROM TABLE2), не поддерживаются. - Запросы INSERT, содержащие несколько выражений VALUE (например,
INSERT INTO TABLE VALUES (1, 2) (3, 4)), не поддерживаются. - Запросы INSERT, за которыми следует предложение OPTION, соединённые с несколькими таблицами или за которыми следует другой запрос, не поддерживаются.
-
IDENTITY_INSERTне управляется в драйвере. Либо не включайте столбцы идентификаторов в операторы insert, либо вручную задавайте состояниеIDENTITY_INSERTваших таблиц между операторами пакетной вставки, либо вручную передавайте явное значение для столбца идентификатора в операторе insert. Дополнительные сведения см. в разделе SET IDENTITY_INSERT. - Из-за ограничений API массового копирования типы данных
MONEY,SMALLMONEY,DATE,DATETIME,DATETIMEOFFSET,SMALLDATETIME,TIME,GEOMETRYиGEOGRAPHYв настоящее время не поддерживаются для этой функции в Azure SQL DW.
Если запрос завершается ошибкой из-за ошибок, не связанных с экземпляром SQL Server, драйвер записывает сообщение об ошибке и возвращается к исходной логике для пакетной вставки.
Пример
В этом примере демонстрируется использование пакетной вставки 1000 строк как в обычном сценарии, так и при использовании API Bulk Copy.
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.