在 mssqlserver 中使用 jdbc 的 Massive Insert/Update 的最佳策略

Best strategy for Massive Insert/Update using jdbc in mssqlserver

你好,我之前发过这个问题,但好像我还不够清楚,所以我会尽量在这里详细说明我的情况。

我需要实施一个解决方案,每天从一些 CSV 文件中提取数据并仅使用 JDBC 将此数据插入生产环境数据库 tables。

我必须插入 2 tables

表格:

    Table1 (
    [func] [varchar](8) NOT NULL,
    [Ver] [smallint] NOT NULL,
    [id] [varchar](32) NOT NULL,
    [desc] [varchar](300) NOT NULL,
    [value] [float] NOT NULL,
    [dtcreated] [date] NOT NULL,
    [dtloaded] [date] NULL,
 CONSTRAINT [Table1_PK] PRIMARY KEY CLUSTERED 
(
    [func] ASC,
    [ver] ASC,
    [id] ASC,
    [desc] ASC,
    [dtcreated] ASC
);

table2 (
    [id] [varchar](32) NOT NULL,
    [f1] [varchar](50) NOT NULL,
    [f2] [varchar](32) NOT NULL,
    [f3] [varchar](6) NULL,
    [f4] [varchar](3) NULL,
    [f5] [varchar](3) NULL,
    [f6] [varchar](32) NULL,
    [DtStart] [date] NOT NULL,
    [DtEnd] [date] NOT NULL,
    [dtcreated] [date] NOT NULL,
    [dtloaded] [date] NULL,
    CONSTRAINT [table2_PK] PRIMARY KEY CLUSTERED 
    (
        [id] ASC,
        [DtStart] DESC,
        [DtEnd] DESC
    )

表 1 的大小为 400+GB,有 6,500+ 百万条记录。 Table2 有 30+GB 的大小,大约有 500 万条记录。

在 table1 中,我需要处理并插入 150 万条记录。

在 table2 中,我需要处理 update/insert 110 万条记录,这是使用匹配时合并查询完成的。

我需要能够在不中断使用这些 table 的情况下执行这两个过程。

我的代码执行以下操作

public void processFile(String fileLocation) throws IOException, SQLException{
    try {

        SqlClient sqlClient = SqlClient.from(DriverClassName.SQLSERVER, DriverConnectionString.barra());
        Connection connection = sqlClient.getConnection();

        PreparedStatement pstmt  = connection.prepareStatement(getSql());

        File file = new File(fileLocation);

        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            int lnproc = 0;
            int batchCount = 0;
            String line;
            while (((line = br.readLine()) != null) {
    
                String[] parts = line.split(",");
                pstmt.clearParameters();
                .....//Process parts and add them to the preparestatement
                pstmt.addBatch();
                batchCount++;
    
                if(batchCount>=batchSize){
                    batchCount = 0;
                    try {
                        pstmt.executeBatch();
                    }catch (BatchUpdateException ex){               
                    }
                }
            }

            try {
                pstmt.executeBatch();
            }catch (BatchUpdateException ex){
            }
        }

        connection.commit();
        connection.close();
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
    }
}

由于要在每个 table 中插入大量记录,我可以在 table 上生成不同的锁,这会影响生产环境。

我做了一些研究,我有多种策略正在考虑使用

我想就您认为在这种情况下使用的最佳策略向社区征求意见。

以及您可以向我提出的任何建议。

经过调查,我找到了以下最佳解决方案,

首先如评论中所述,我读取了整个文件并将其以 java 结构加载到内存中。

加载文件后,我迭代 java 更严格并开始加载批处理中的每条记录。同时,我在添加批次的每个项目上都保留了一个计数器。 当计数器达到 5000 时,我对批次进行提交,将计数器重置为 0 并继续添加到以下项目我再次达到 5000 或到达迭代结束。

通过这样做,我阻止了 MSSQL 在 table 上创建锁,并且 table 仍然可以被其他进程和应用程序使用。