gpt4 book ai didi

java - Azure:超出了准备语句每个 session 20 MB 的内存限制

转载 作者:行者123 更新时间:2023-11-30 02:31:30 25 4
gpt4 key购买 nike

我正在执行很多批处理,其中包含准备好的 insert 语句

public static void main(String... args) throws Exception {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
BufferedReader csv = new BufferedReader(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("records.csv")));
String line;
createConnectionAndPreparedStatement();
while ((line = csv.readLine()) != null) {
tupleNum++;
count++;
List<String> row = new ArrayList<String>(Arrays.asList(line.split(";")));

tupleCache.add(row);
addBatch(row, ps);
if (count > BATCH_SIZE) {
count = 0;
executeBatch(ps);
tupleCache.clear();
}
}
}

protected static void createConnectionAndPreparedStatement() throws SQLException {
System.out.println("Opening new connection!");
con = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
con.setAutoCommit(true);
con.setAutoCommit(false);
ps = con.prepareStatement(insertQuery);

count = 0;
}


private static void executeBatch(PreparedStatement ps) throws SQLException, IOException, InterruptedException {
try {
ps.executeBatch();
} catch (BatchUpdateException bue) {
if (bue.getMessage() != null && bue.getMessage().contains("Exceeded the memory limit")) {
// silently close the old connection to free resources
try {
con.close();
} catch (Exception ex) {}
createConnectionAndPreparedStatement();
for (List<String> t : tupleCache) {
addBatch(t, ps);
}
// let's retry once
ps.executeBatch();
}
}
System.out.println("Batch succeeded! -->" + tupleNum );
con.commit();
ps.clearWarnings();
ps.clearBatch();
ps.clearParameters();
}

private static void addBatch(List<String> tuple, PreparedStatement ps) throws SQLException {
int sqlPos = 1;
int size = tuple.size();
for (int i = 0; i < size; i++) {
String field = tuple.get(i);
//log.error(String.format("Setting value at pos [%s] to value [%s]", i, field));
if (field != null) {
ps.setString(sqlPos, field);
sqlPos++;
} else {
ps.setNull(sqlPos, java.sql.Types.VARCHAR);
sqlPos++;
}
}
ps.addBatch();
}

因此,在独立应用程序中,一切都很好,并且在 700k 批量插入后没有发生异常。但是,当我在大约 6-7k 批量插入后在自定义 Pig StoreFunc 中执行实际相同的代码时,出现以下异常:

java.sql.BatchUpdateException: 112007;Exceeded the memory limit of 20 MB per session for prepared statements. Reduce the number or size of the prepared statements.
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeBatch(SQLServerPreparedStatement.java:1824)

只有重新启动连接才有帮助。有人可以帮助我了解为什么会发生这种情况以及如何解决它吗?

最佳答案

根据您的描述和错误信息,根据我的经验,我认为该问题是由SQL Azure服务器端的内存配置引起的,例如服务器资源池内连接的内存限制。

我试图顺着线索寻找有关连接内存限制的具体说明,但没有成功,除了here中的以下内容之外.

Connection Memory

SQL Server sets aside three packet buffers for every connection made from a client. Each buffer is sized according to the default network packet size specified by the sp_configure stored procedure. If the default network packet size is less than 8KB, the memory for these packets comes from SQL Server's buffer pool. If it's 8KB or larger, the memory is allocated from SQL Server's MemToLeave region.

然后我继续搜索packet size & MemToLeave并查看它们。

根据以上信息,我猜测“Exceeded the memory limit of 20 MB per session for prepared statements”是指并行连接使用的所有内存超过SQL Azure实例的最大内存缓冲池。

因此,我建议您可以尝试两种解决方案。

  1. 建议减小BATCH_SIZE变量的值,使服务器内存消耗小于内存缓冲池的最大大小。
  2. 尝试扩展您的 SQL Azure 实例。

希望有帮助。

<小时/>

这里有两个新建议。

  1. 我真的不确定 MS jdbc 驱动程序是否支持当前使用 Apache Pig 的场景,就像并行 ETL 作业一样。请尝试使用 jtds jdbc 驱动程序而不是 MS 驱动程序。
  2. 我认为更好的方法是使用更专业的工具来做到这一点,例如 sqoopkettle

关于java - Azure:超出了准备语句每个 session 20 MB 的内存限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44188234/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com