Java 如何有效地为多个重复的表保存值?

Java 如何有效地为多个重复的表保存值?,java,database,oracle,performance,java.util.concurrent,Java,Database,Oracle,Performance,Java.util.concurrent,我有一个名为Message的实体,它包含以下字段:id(PK)、字符串messageXML和时间戳日期。以及将对象存储到Oracle数据库(11g)/MyBatis中的简单dao 代码如下所示: 服务: void process throws ProcessException { Message message = wrapper.getMessage(request); Long messageId; try { messageId = (Long) dao.save(message); }

我有一个名为Message的实体,它包含以下字段:id(PK)、字符串messageXML和时间戳日期。以及将对象存储到Oracle数据库(11g)/MyBatis中的简单dao

代码如下所示:

服务:

void process throws ProcessException {
Message message = wrapper.getMessage(request);
Long messageId;
try {
messageId = (Long) dao.save(message);
} catch (DaoException e) {
throw ProcessException(e);
}

简单的代码。不幸的是,此方法进程(req)的负载约为500 req/秒。有时我在保存消息时会锁定数据库

为了解决这个问题,我考虑了乘法表消息,例如,我将有五个表消息1,消息2。。。消息5和保存实体消息期间,我将绘制(类似循环算法)表-例如:

private Random generator; 

public MessageDao() {
this.generator = new Random();

Serializable save(Message message) throws DaoException {
try {
     getSqlSession().insert(getMapperName() + ".insert", message); 
return message.getPrimaryKey();
} catch (Exception e) {
throw DaoException(e);
}

private String getMapperName() {
return this.mapperName.concat(String.valueOf(generator.nextInt(5))); //could be more effeciency of course
}

你对这个解决方案有什么想法?是否可以有效?我怎样才能做得更好?我在哪里可以制造瓶颈?

从字里行间看,我猜您有许多代码实例正在运行,为多个并发请求提供服务,因此您会遇到争用。或者您有一台服务器每秒发出500个请求,您会遇到等待。你指的是哪一个。在前一种情况下,您可能希望查看扩展数据块分配—如果表/索引下一个扩展数据块的大小很小,您将在Oracle获取下一个扩展数据块时定期看到延迟。如果大小太小,您将定期得到此延迟,大小太大,并且当它最终用完时,等待时间将更长。您可以每周计算存储量,每周执行一次相应的“增长”表/索引的过程,以避免在操作时间出现这种情况。我很想检查一下统计数据,看看等待是什么


但是,如果原因是并发性(可能是扩展管理之外的原因),那么您可能会在用于强制PK约束的索引上遇到热块争用。缓解这种情况的典型策略包括反向索引(无需更改代码),或者更具争议的是,通过添加一个简单列来进一步隔离并发会话,使用具有较弱唯一约束的分区。例如,通过此列和现有PK列向表和分区添加列serverId。为每个应用服务器分配一个唯一的serverId(配置/启动文件)。修改插入内容以包含服务器ID。每个服务器有一个分区。有争议,因为约束较弱(具体到分区如何工作),这对纯粹主义者来说是一个诅咒,但这是我在Oracle Consulting的项目中使用的,以最大限度地提高Exadata的性能。所以,它就在那里。当然,分区可以被认为是分组到一个超级表中的不同表,因此您编写独立表的想法与这里的建议相差不到一百万英里。分区的优点它是对这些数据进行分组的一种更自然的机制,添加一个新分区所需的工作比扩展时添加一个新表所需的工作要少。

我不明白为什么会因为创建而获得数据库锁。可能是其他一些更新值的过程,或者由于外键上缺少索引而导致表锁已满?这些都是好主意,但可能没有一个与此相关。第一步可能是使用AWR之类的工具来找出数据库在等待什么(我猜:没什么,这是网络问题)。考虑批处理与逐行处理可能有助于解决问题。例如,编写一个简单的(可能是并行的)SQL语句来插入伪行。如果它可以每秒插入50000行而不是500行,请尝试找出原因。
private Random generator; 

public MessageDao() {
this.generator = new Random();

Serializable save(Message message) throws DaoException {
try {
     getSqlSession().insert(getMapperName() + ".insert", message); 
return message.getPrimaryKey();
} catch (Exception e) {
throw DaoException(e);
}

private String getMapperName() {
return this.mapperName.concat(String.valueOf(generator.nextInt(5))); //could be more effeciency of course
}