【问题标题】:Java Hibernate Database speed issueJava Hibernate 数据库速度问题
【发布时间】:2018-08-22 11:23:57
【问题描述】:

我使用 Jhipster 生成了应用程序。一开始一切正常,但随着应用程序的增长,锦标赛实体成为有关性能的问题。 这是我的实体:

/**
 * A Tournament.
 */
@Entity
@Table(name = "tournament")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Document(indexName = "tournament")
public class Tournament implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "location")
    private String location;

    @Column(name = "url")
    private String url;

    @Column(name = "start_date")
    private ZonedDateTime startDate;

    @Column(name = "end_date")
    private ZonedDateTime endDate;

    @Column(name = "entry_fee")
    private Double entryFee;

    @Column(name = "prize")
    private Double prize;

    @Column(name = "goods")
    private String goods;

    @Column(name = "favorite_rating")
    private Long favoriteRating;

    @Column(name = "participants_number")
    private Integer participantsNumber;

    @Column(name = "finished")
    private Boolean finished;

    @Column(name = "view_only")
    private Boolean viewOnly;

    @Column(name = "image")
    private String image;

    @Column(name = "description")
    private String description;

    @Column(name = "teams_applied")
    private String teamsApplied;

    @Lob
    @Column(name = "schedule")
    private String schedule;

    @Lob
    @Column(name = "prize_distribution")
    private String prizeDistribution;

    @Lob
    @Column(name = "contacts")
    private String contacts;

    @Lob
    @Column(name = "rules")
    private String rules;

    @OneToMany(mappedBy = "tournament", fetch = FetchType.LAZY)
    @JsonIgnore
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    private Set<Stream> streams = new HashSet<>();

    @ManyToMany
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @JoinTable(name = "tournament_platforms", joinColumns = @JoinColumn(name = "tournaments_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "platforms_id", referencedColumnName = "id"))
    private Set<Platform> platforms = new HashSet<>();

    @ManyToMany(mappedBy = "favoriteTournaments", fetch = FetchType.LAZY)
    @JsonIgnore
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    private Set<User> favoriteUsers = new HashSet<>();

    @ManyToOne
    private Game game;

    @ManyToOne
    private TournamentStatus status;

    @ManyToOne
    private EntryType entryType;

    @ManyToOne
    private TournamentFormat format;

    @ManyToOne
    private Region region;

    @ManyToOne
    private GameMode gameMode;

    @ManyToOne
    private PrizeType prizeType;

    @ManyToOne
    private Organizer organizer;

    @ManyToOne
    private TournamentStage stage;

    @ManyToOne
    private HostPlatform hostPlatforms;

    @ManyToOne
    private TournamentType type;

    @ManyToOne
    private PlayType playType;

    @ManyToOne
    private Currency currency;

    @ManyToOne
    private Country country;

我正在使用 Spring JPA。从数据库中获取 20 场比赛需要 39 秒。这是不可接受的。有什么办法可以降低到正常速度。如此长的响应时间是什么原因?我把每一个多对一的关系都做成了单一的

【问题讨论】:

  • 您是否曾经直接对数据库执行过相同的查询?可能不仅仅是休眠的问题。此外,您还有大量的直接依赖项也将被加载,这可能会导致巨大的对象。此外,您应该真正考虑lazy-loading 每个依赖项
  • “正常速度”?我在您的对象中计算了 15 个 JOIN - 我错过了任何一个吗?这是查询引擎要做的大量工作。我的建议是对您的模式进行非规范化以查看性能是否有所提高并且不使用 JPA。手写SQL。当黑匣子让你如此失望时,它们就会有问题。

标签: java hibernate spring-data-jpa jhipster


【解决方案1】:

在 hibernate 的 JPA 实现中,@ManyToOne 默认有一个 fetchType = EAGER,而你有 14 个。

@ManyToOne
private Country country;

这意味着每个请求有 14 个加入。我强烈建议对所有关系使用fetchType = LAZY,并在需要时一一停用。

根据经验,每个请求的连接数不应超过 3 个。

还可以查看生成的请求并使用EXPLAIN PLAN 以了解数据库的实际用途以及成本高昂的地方。它可能会在用作外键的列上显示一些缺失的索引...

【讨论】:

  • 更不用说潜在的嵌套连接
  • 我如何使用解释计划?
  • 如果我都需要它们怎么办?
  • @user3364181 通常,您不需要全部。例如,我怀疑您不需要 RegionCountry 每次。考虑使用JPA Criteria API 来构建您的请求并仅选择您真正需要的内容。
  • 总是使用fetchType = LAZY。您可以在查询中使惰性关系变得急切(例如JOIN FETCH),但不能使急切关系变得惰性。
猜你喜欢
  • 1970-01-01
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
相关资源
最近更新 更多