我的表结构包含许多与用户表相关的表:
Paginator
因此,用户可以拥有他想要的尽可能多的邮件,地址和电话号码。有一个广泛的搜索表单来搜索成员,包括来自其他表的连接值;例如,它可以搜索用户地址或他的电话号码。
为了能够搜索其他表中的值,我在搜索用户时加入所有相关表。
由于某些用户拥有相当数量的数据,这意味着查询中的行数约为~30k。实际上没有问题,查询在< 1秒钟,完全没问题。
// User Repository
public function findUserByCriteria($criteria, $offset, $limit) {
$qb = $this->createQueryBuilder('u');
$qb->leftJoin('u.emails', 'e')->addSelect('u');
$qb->leftJoin('u.addresses', 'adr')->addSelect('adr');
$qb->leftJoin('u.phonenumbers', 'phn')->addSelect('phn');
// 4 more joins
// ...
// the actual search implementation goes here...
// ....
$qb->setFirstResult($offset);
$qb->setMaxResults($limit);
return new Paginator($qb, true);
}
组件发挥作用后,它开始变得怪异。我的存储库方法看起来与此类似:
Paginator
问题似乎来自fetchJoinCollection
构造函数true
的第二个参数。只要在false
上,找到一些用户(那些拥有大量数据的用户)需要大约10秒钟,而{{1}时只需要大约1秒钟。 }。设置为false
时的问题是整个分页都搞砸了。
我发现删除方法顶部的连接也会将执行时间减少到大约1秒左右,但之后就无法在这些表中进行搜索了。
这里发生了什么?
答案 0 :(得分:0)
连接很重,左连接更重。
您可以根据findUserByCriteria
参数更改$criteria
方法以根据需要添加连接。例如,如果没有地址标准,则无需加入Address
实体。
如果您的查询仍然太慢,您可以直接使用PDO创建它们,这比使用querybuilder或DQL更快。
答案 1 :(得分:0)
您可以尝试避免使用Paginator
,这是一项涉及大量数据的痛苦。
在这种情况下,我会做下一步:首先我计算数据总数(COUNT)并将该值用于我的分页,其次我通过查询获取数据。
此示例使用DQL而不是“查询”构建器,但您可以理解:
$countDql = "SELECT COUNT (e.id)
FROM YourBundle:Entity e
WHERE e.condition = :yourCondition";
$dataDql = "SELECT e
FROM YourBundle:Entity e
WHERE e.condition = :yourCondition";
$total = $em->createQuery($countDql)->getSingleScalarResult(); //Add also setParameter() if needed
$data = $em->createQuery($dataDql)->getResult();
希望它有所帮助。