我在应用程序中有一个进程,我们在应用程序中插入1000多条记录。表格中有一个属性如下所述。
@Index(name = "_IDX_UNIQUE_UUID", columnNames = {"UUID"})
@Column(name = "UUID", nullable = false)
private Long uuid;
在填充实体类期间,值设置如下
entity.setUuid(service.getNextUuid());
在服务类中调用此方法:
public Long getNextUuid() {
Query query = entityManager.createNativeQuery("select nextval('seq_xxxx_uuid')");
//This takes lot of time to execute
Obj result = query.getSingleResult();
return ((BigInteger) result).longValue();
}
要从序列中获取下一个值,需要大约200-700 ms。如果我尝试插入1000多条记录,这会累积到几分钟。此外,查询非常简单,如果我在数据库客户端执行它,则执行时间不到1毫秒。
我正在使用postgresql 9.4-1206-jdbc4,hibernate 4.2.0.Final和Spring 4.2.5。
答案 0 :(得分:0)
这很慢,因为您正在经历JPA完整查询的所有安全性和一致性检查层,而且您每次都创建一个新的NativeQuery对象,而不是通过@NamedNativeQuery
创建它,因此花更多的时间来评估。
解决方案是使用以下内容对列进行注释:
@Id
@Index(name = "_IDX_UNIQUE_UUID", columnNames = {"UUID"})
@SequenceGenerator(name = "seq_xxxx_uuid_gen", sequenceName = "seq_xxxx_uuid", allocationSize = 1)
@GeneratedValue(generator = "seq_xxxx_uuid_gen")
@Column(name = "UUID", nullable = false)
private Long id;
您确实希望allocationSize
与序列的increment_by
值相同,否则在第一次持续存在后您将遇到其他问题。
如果您需要将该Id用于多个对象(比如它是复合键的一部分,但只有部分是串行生成的),只需在持久化后从第一个中抓取它。
编辑:
或者,您可以放弃SequenceGenerator并使用它:
@GeneratedValue(strategy = GenerationType.IDENTITY)
如果生成的查询已正确优化并在插入时使用java.sql.Statement.getGeneratedKeys()
,则速度可能会更快。