在一个项目中,我们使用 Querydsl 创建动态查询并应用排序和分页。当以下对象中存在一对多和多对一关系时,以下代码非常慢
在一个项目中,我们使用 Querydsl 创建动态查询并应用排序和分页。当以下对象 ticket、payment 和 ticket_payment 中存在 oneTomany 和 manytoone 关系时,以下代码非常慢。
特别是在此部分应用分页时,需要 10 多分钟才能返回 10 个项目。
List<?> result = querydsl.applyPagination(pageable, query).fetch();
可分页的值为 offset=0、size=10,并且有用于排序的值。
在生成的查询中没有添加“获取第一个?仅获取行”部分,所以我猜想它花费的时间太长,因为它加载了 ticket 和 ticket_payment 表?Ticket 表有 100K 行,Ticket_payment 有 120k。在 sql developer 中运行相同的查询时,返回 50 行只需不到 4 秒。
为了更快地获得结果,可以进行哪些改进?是否可以定制 fetch() 方法以使其运行得更快?
QueryDSL 获取代码:
org.springframework.data.domain.PageImpl;
org.springframework.data.domain.Pageable;
Querydsl querydsl = new Querydsl(entityManager, (new PathBuilderFactory()).create(<EntityClass>.class));
JPQLQuery<?> query = new JPAQuery<>(entityManager);
//TODO: prepare your query here
//Get the count
Long totalElements = query.fetchCount();
//Apply the pagination
List<?> result = querydsl.applyPagination(pageable, query).fetch();
//Returns 10 items but takes more than 10min
//return a paged response
return new PageImpl<>(result, pageable, totalElements);
以及以下实体和表格
票
@Entity
@Table(name = "TICKET")
public class Ticket implements Serializable {
@Id
@Column(name = "TICKET_ID", nullable = false)
private Long id;
@OneToMany(mappedBy = "Ticket")
private Set<TicketPayment> ticketPayments= new HashSet<>();
...
}
支付
@Entity
@Table(name = "PAYMENT")
public class Payment implements Serializable {
@Id()
@Column(name = "PAYMENT_ID")
private Long id;
@Column(name = "PAYMENT_CODE")
private String code;
连接表
@Entity
@Table(name = "TICKET_PAYMENT")
@IdClass(TicketPaymentPK.class)
public class TikcetPayment{
@Id
@Column(name = "TICKET_ID", nullable = false, precision = 0)
private long ticketId;
@Id
@Column(name = "PAYMENT_ID", nullable = false, precision = 0)
private long paymentId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TICKET_ID", referencedColumnName = "TICKET_ID", nullable = false, insertable = false, updatable = false)
private Ticket ticket;
@ManyToOne
@JoinColumn(name = "PAYMENT_ID", referencedColumnName = "PAYMENT_ID", nullable = false, insertable = false, updatable = false)
private Payment payment;
...
复合键
public class TicketPaymentPKimplements Serializable {
@Id
@Column(name = "TICKET_ID", nullable = false, precision = 0)
private long ticketId;
@Id
@Column(name = "PAYMENT_ID", nullable = false, precision = 0)
private long paymentId;