我在sql server中有一个存储过程:
CREATE OR ALTER PROCEDURE dbo.basic_json_normalization_full
@tableNamep sysname,
@tableName sysname,
@columns_list NVARCHAR(MAX),
@json_query NVARCHAR(MAX),
@rows_count INT OUTPUT AS BEGIN
SET NOCOUNT, XACT_ABORT ON;
DECLARE @main_tableName NVARCHAR(MAX) = 'dbo.' + @tableName;
DECLARE @raw_tableName NVARCHAR(MAX) = 'dbo.' + 'raw' + @tableNamep;
-- Truncate the main table DECLARE @truncateQuery NVARCHAR(MAX);
SET @truncateQuery = 'TRUNCATE TABLE dbo.' + @tableName;
EXECUTE sp_executesql @truncateQuery;
-- Construct the dynamic SQL
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'
BEGIN TRAN;
INSERT INTO ' + @main_tableName + '
(_id, ORIGINAL_ID, ' + @columns_list + ')
SELECT j.[_id], j.[ORIGINAL_ID], ' + @columns_list + '
FROM ' + @raw_tableName + ' r
CROSS APPLY OPENJSON(r.raw_data)
WITH ( _id nvarchar(155) ''$._id'', ORIGINAL_ID NVARCHAR(150) ''$.ORIGINAL_ID'', ' + @json_query + ') AS j;
SET @rows_count = @@ROWCOUNT;
COMMIT TRAN;
';
-- Execute the dynamic SQL
EXEC sp_executesql @sql, N'@rows_count int OUTPUT', @rows_count = @rows_count OUTPUT; END; GO
此过程在 Spring Batch Tasklet 中使用,更具体地说是在名为
JsonNormalize
的方法中使用:
@Override
public int jsonNormalize(JdbcTemplate jdbcTemplate, String tableName, String chargement) {
return simpleJdbcCall.withProcedureName("basic_json_normalization_full")
.withSchemaName("dbo")
.declareParameters(new SqlParameter("@tableName", Types.NVARCHAR))
.declareParameters(new SqlParameter("@tableNamep", Types.NVARCHAR))
.declareParameters(new SqlParameter("@columns_list", Types.NVARCHAR))
.declareParameters(new SqlParameter("@json_query", Types.NVARCHAR))
.execute(in);
}
这是 tasklet 片段代码:
@Bean
public Step BasicNormalization(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder(String.join("", BASIC_NORMALIZATION), jobRepository)
.tasklet(basicNormalizationTasklet(), transactionManager)
.throttleLimit(5)
.build();
}
有什么方法可以让这个更快一点,因为到目前为止,处理 120 万行需要 4 个小时。
PS:我尝试在 SQL Server Management Studio 中执行此操作,它也花费了太长的时间,因此有什么方法可以在 Spring Batch 中使用多线程或分区选项来使其更快。
多线程不会提高步骤的性能,甚至可能会产生不正确的结果,因为多个线程会在同一数据集上同时执行相同的过程。
您可以尝试对输入数据集进行分区并配置分区步骤,其中每个工作线程处理不同的分区(即每个线程将在不同的数据集上调用该过程)。