查询下一个序列生成需要很长时间

时间:2016-10-17 09:37:08

标签: postgresql hibernate jpa

我在应用程序中有一个进程,我们在应用程序中插入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。

1 个答案:

答案 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(),则速度可能会更快。