我有一个Spring Boot项目设置为使用带有Hibernate的MySQL数据库。我最近在我的数据库表中添加了30k个新条目,从那时起,查询速度非常慢。
我使用Query DSL自己执行查询。 假设我有以下Candidate实体与CandidateField实体具有OneToMany关系:
@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
CandidateField实体:
@Autowired
CandidateRepository repository;
QCandidate candidate = QCandidate.candidate;
BooleanExpression predicate = candidate.fields.any().name.eq("Accounting");
Iterable<Candidate> results = repository.findAll(predicate);
最后,这是我的搜索代码:
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]
最后一行需要大约8分钟来搜索30k记录数据库(没有索引字段),结果为80行。问题在本地和我的在线登台服务器中是相同的。它会生成此查询,然后暂停8分钟:
EXPLAIN SELECT *
FROM Candidates
INNER JOIN Candidate.CandidateFields
WHERE CandidateFields.CandidateID = Candidates.CandidateID AND
CandidateFields.Name = "Accounting";
编辑:问题肯定源于自动生成的查询中的EXISTS子句。我现在必须研究它为什么这样做以及如何使它生成更有效的查询
奇怪的是,如果我做一个没有任何参数的简单findAll(),它实际上似乎是选择和解析结果而不是暂停。如果我按ID而不是名称搜索,问题仍然存在。
在我的数据库管理工具中运行实际的SQL查询会在大约1秒内返回结果(这里是按请求使用EXPLAIN结果的查询):
<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>
结果:
SRC_URI = "svn://URL_TO_THE_TARGET_PROJECT \
file://host-minify-asset-script.js"
DEPENDS = "nodejs-native "
RDEPENDS_${PN} = "nodejs "
inherit npm npm-install
do_install() {
# This build/install dependency for target ?
oe_runnpm install
oe_runnpm prune --production
# Is it the proper way to install node-minify on the host like this ?
oe_runnpm_native install https://github.com/srod/node-minify/tarball/2.0.2
# Now, how can I run natively my script (host-minify-asset-script.js)
# to minify the assets present in the work folder of the recipe ?
}
&#13;
编辑:问题肯定源于自动生成的查询中的EXISTS子句。我现在必须研究它为什么这样做以及如何使它生成更有效的查询
感谢任何人和所有人的帮助。如果需要也可以澄清。干杯!
答案 0 :(得分:0)
没有字段被编入索引
为什么不呢?只需在此添加此索引:
CREATE INDEX i1 ON Candidate.CandidateFields(Name);
对于此特定查询甚至更快:
CREATE INDEX i2 ON Candidate.CandidateFields(Name, CandidateID);
因为后者将是半连接(EXISTS()
子查询)的覆盖索引。