JPA + spring 启动 - 当数据库很大时 findBy <field> 非常慢(20M 行 Table )

JPA + spring boot - findBy <field> extremely slow when Database is huge ( 20M lines Table )

我需要关于 JPA spring 数据的关联。 我有使用 MySQL 和 20GB 数据(20 米行)的数据库。 当我执行 findByID (String id) - (不是唯一标识符)。 需要10多分钟...

什么是性能问题??

我的对象实体:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long rootId;

private String address;


private String check_in_time;

private String check_out_time;

@OneToMany(mappedBy = "data" , fetch = FetchType.LAZY)
private Set<DescriptionStruct> description_struct;

private String id;

@ElementCollection(fetch = FetchType.LAZY)
private Set<String> images;

private String kind;

private double latitude;

private double longitude;

private String name;

private String phone;

@Embedded
private Star_certificate star_certificate;

private String postal_code;


@AttributeOverrides({ @AttributeOverride(name = "id", column = @Column(name = "R_ID")),
        @AttributeOverride(name = "name", column = @Column(name = "R_NAME")) })
@Embedded
private Region region;

private int star_rating;

private String email;

private int semantic_version;

@ElementCollection(fetch = FetchType.LAZY)
private Set<String> serp_filters;

private boolean is_closed;

@Embedded
private MetapolicyStruct metapolicy_struct;

private String metapolicy_extra_info;

@Embedded
private Facts facts;

@ElementCollection(fetch = FetchType.LAZY)
private Set<String> payment_methods;

private String hotel_chain;

@OneToMany(mappedBy = "data", fetch = FetchType.LAZY)
private Set<AmenityGroup> amenity_groups;

@OneToMany(mappedBy = "data", fetch = FetchType.LAZY)
private Set<RoomGroup> room_groups;

@OneToMany(mappedBy = "data", fetch = FetchType.LAZY)
private Set<PolicyStruct> policy_struct;

我的函数:

@Autowired 私有数据存储库数据存储库;

public regionSearchData returnFullData(regionSearchResponseRH response) {
    
    regionSearchData data = new regionSearchData();

    
    response.getData().getHotels().forEach(H -> {

        Data hotelD = dataRepository.findById(H.getId());
        if (hotelD != null) {
            RatesSearch R = H.getRates().get(0);
            R.setAddress(hotelD.getAddress());
            R.setImages(hotelD.getImages());
            R.setStar_certificate(hotelD.getStar_certificate());
            R.setStar_rating(hotelD.getStar_rating());
            R.setName(hotelD.getName());
                
        }
        
        });
    
    data.setTotal_hotels(response.getData().getTotal_hotels());
    data.setHotels(response.getData().getHotels()); 

    return data;
    
    
    
}

Hibernate 统计数据:

16893585 nanoseconds spent preparing 42 JDBC statements;
347535215661 nanoseconds spent executing 42 JDBC statements;
656641754926 nanoseconds spent executing 82 JDBC statements;

如果我删除 findBy 需要 10 秒...

谢谢, 伊丹

肯定有不止一种你可以尝试的事情。您的代码需要十多分钟,可能是因为它通过网络对数据库进行了多次往返。 请记住,不仅数据库搜索需要更多时间,从您的应用程序到网络的数据库往返也需要更多时间,我怀疑这里就是这种情况。

根据您的用例,您可以做的第一件事是最小化到 DB 的往返行程并在 for 循环中调用 findById () 是最糟糕的事情。 以下是我的建议

  1. 正在为您搜索的字段添加索引
  2. 避免在 for 循环中调用 findById (),您可以使用其他一些存储库方法,或者您可以编写 findByIdsIn(ids 列表),具体取决于此 for 循环的大小 - 您可以一次传递所有 id或使用批处理方法,例如一次获取 20-30 个实体并执行您的业务逻辑。
  3. 您有许多表使用@oneToMany 或@ElementCollection 连接到您的实体,您需要检查hibernate 是否正在为此执行N+1 查询,如果是,请先解决该问题。