Spring Data查询非常慢

时间:2016-12-22 17:49:36

标签: java mysql hibernate spring-boot querydsl

我有一个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>

结果:

&#13;
&#13;
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;
&#13;
&#13;

编辑:问题肯定源于自动生成的查询中的EXISTS子句。我现在必须研究它为什么这样做以及如何使它生成更有效的查询

感谢任何人和所有人的帮助。如果需要也可以澄清。干杯!

1 个答案:

答案 0 :(得分:0)

  

没有字段被编入索引

为什么不呢?只需在此添加此索引:

CREATE INDEX i1 ON Candidate.CandidateFields(Name);

对于此特定查询甚至更快:

CREATE INDEX i2 ON Candidate.CandidateFields(Name, CandidateID);

因为后者将是半连接(EXISTS()子查询)的覆盖索引。