나는 Hibernate에서 MySQL 데이터베이스를 사용하도록 스프링 부트 프로젝트를 설정했다. 최근에 데이터베이스 테이블에 30,000 개의 새 항목을 추가했으며 그 이후로 쿼리가 심하게 느려졌습니다.봄 데이터 쿼리가 매우 느림
저는 쿼리 DSL을 사용하여 쿼리를 직접 수행합니다.
@Entity
@Table(name = "Candidates", schema = "Candidate")
public class Candidate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CandidateID")
private Long candidateID;
@Column(name = "FirstName")
private String firstName;
@Column(name = "LastName")
private String lastName;
@Column(name = "Zip")
private String zip;
@Column(name = "Email")
private String email;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "candidate")
private List<CandidateField> fields;
//Constructors, getters, setters omitted
CandidateField 엔티티 : 나는 CandidateField 엔티티와 OneToMany 관계를 다음과 같은 후보의 실체가 있다고 가정
@Autowired
CandidateRepository repository;
QCandidate candidate = QCandidate.candidate;
BooleanExpression predicate = candidate.fields.any().name.eq("Accounting");
Iterable<Candidate> results = repository.findAll(predicate);
: 마지막으로, 여기
@Entity
@Table(name = "CandidateFields", schema = "Candidate")
public class CandidateField {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CandidateFieldID")
@JsonIgnore
private Long candidateFieldID;
@JsonIgnore
@Column(name = "CandidateID")
private Long candidateID;
@Column(name = "Name")
private String name;
@ManyToOne
@JoinColumn(name = "CandidateID", referencedColumnName = "CandidateID", insertable = false, updatable = false)
@JsonIgnore
private Candidate candidate;
//Constructors, getters, setters omitted
그리고 나의 검색 코드 마지막 행은 80 행의 결과와 함께 30k 레코드 데이터베이스 (필드가 인덱싱되지 않음)를 검색하는 데 약 8 분이 소요됩니다. 문제는 로컬 및 내 온라인 준비 서버에서 동일합니다. 그것은 8 분 동안 일시 정지 후이 쿼리를 생성 :
select candidate0_.CandidateID as Candidat1_4_, candidate0_.Email as
Email7_4_, candidate0_.FirstName as FirstNam8_4_, candidate0_.LastName as
LastNam17_4_, candidate0_.Zip as Zip30_4_ from Candidate.Candidates
candidate0_where exists (select 1 from Candidate.CandidateFields fields1_
where candidate0_.CandidateID=fields1_.CandidateID and fields1_.Name=?)
binding parameter [1] as [VARCHAR] - [Accounting]
편집 : (가) 자동 생성 된 쿼리에 EXISTS 절에서 문제가 확실히 유래한다. 이제 왜 그렇게하는지, 더 효율적인 쿼리를 생성하는 방법을 살펴보아야합니다.
이상한 부분은 매개 변수없이 간단한 findAll()을 수행하면 실제로 선택 및 구문 분석하는 것입니다. 결과보다는 일시 중지. 이름보다는 ID로 검색하면 문제가 지속됩니다.
EXPLAIN SELECT *
FROM Candidates
INNER JOIN Candidate.CandidateFields
WHERE CandidateFields.CandidateID = Candidates.CandidateID AND
CandidateFields.Name = "Accounting";
결과 :
<table>
<tr>
<th>id</th>
<th>select_type</th>
<th>table</th>
<th>partitions</th>
<th>type</th>
<th>possible_keys</th>
<th>key</th>
<th>key_len</th>
<th>ref</th>
<th>rows</th>
<th>filtered</th>
<th>extra</th>
</tr>
<tr>
<td>1</td>
<td>SIMPLE</td>
<td>CandidateFields</td>
<td>null</td>
<td>ALL</td>
<td>null</td>
<td>null</td>
<td>null</td>
<td>null</td>
<td>30601</td>
<td>10</td>
<td>Using where</td>
</tr>
<tr>
<td>1</td>
<td>SIMPLE</td>
<td>Candidates</td>
<td>null</td>
<td>eq_ref</td>
<td>PRIMARY</td>
<td>PRIMARY</td>
<td>4</td>
<td>Candidate.CandidateFields.CandidateID</td>
<td>1</td>
<td>100</td>
<td>Using where</td>
</tr>
</table>
(여기는 요청에 따라 EXPLAIN 결과 쿼리입니다)
편집 : 문제는 확실히 자동 생성 된 쿼리의 EXISTS 절에서 유래합니다. 이제 왜 그렇게하는지, 더 효율적인 쿼리를 생성하는 방법을 살펴보아야합니다.
모든 사항과 모든 도움을 주시면 감사하겠습니다. 필요한 경우 명확히 할 수 있습니다. 건배!
안녕하세요, 이름이 색인 생성되지 않았습니다. 그것은 30k 레코드로 쿼리 속도에 상당한 영향을 미칩니 까?더 자세히 설명해야 할 경우 알려 주시기 바랍니다 –
아마도 "DB 관리 도구"에 EXPLAIN 접두어가 붙은 요청을 입력하고 질문에 결과를 게시하면 CandidateFields의 색인 (CandidateID, Name)이 문제의 해결책이 될 수 있습니다. –
생성 된 쿼리에서'WHERE EXISTS (SELECT 1 FROM correlated subquery) '때문에 오랜 시간이 걸립니다. MySQL은 일반적으로 상관 하위 쿼리를 잘 처리하지 않습니다. 내가 이것에 대해 무엇을해야하는지 알았다면 나는 대답을 썼을 것이다. –