如何解决分页器Knp组件的性能糟糕
我按照本教程https://symfonycasts.com/screencast/doctrine-relations/pagination
因为我需要一种易于分页的查询结果的方法。
但是我对执行简单的计数查询需要多长时间感到惊讶。
这是代码
$pagination = $paginator->paginate($manager->getRepository(
App::getProductClassForGroup($selected_group_code))->findAllWithCurrentUserOptions($user->getId()),$selected_page_number,$product_per_page,array('distinct' => false));
我在第四个参数中添加了array('distinct' => false)
,因为我使用外键作为主键(请参见this github issue)
查询生成器如下:
$queryBuilder->addSelect('prod');
$queryBuilder->innerJoin($this->_alias . '.product','prod');
$queryBuilder->addSelect('users_bookmarks');
$queryBuilder->leftJoin('prod.users_bookmarks','users_bookmarks',Join::WITH,'users_bookmarks.id = :current_user_id');
$queryBuilder->setParameter('current_user_id',$current_user_id);
这是一个非常简单的查询,甚至没有任何where
子句或任何东西。
现在这是knp pagniator service
生成的查询:
102.11 ms
SELECT count(p0_.no_product_w2) AS sclr_0 FROM product_nat p0_ INNER JOIN product p1_ ON
p0_.no_product_w2 = p1_.no_product LEFT JOIN users_bookmark_products u3_ ON
p1_.no_product = u3_.product_no LEFT JOIN User u2_ ON u2_.id = u3_.user_id AND (u2_.id = ?)
Parameters:
[▼
1
]
这是上一个查询的解释:
EXPLAIN
SELECT count(p0_.no_product_w2) AS sclr_0 FROM product_nat p0_ INNER JOIN product
p1_ ON p0_.no_product_w2 = p1_.no_product LEFT JOIN users_bookmark_products u3_
ON p1_.no_product = u3_.product_no LEFT JOIN User u2_ ON u2_.id = u3_.user_id
AND (u2_.id = 1)
_________________________
# id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE p0_ index PRIMARY PRIMARY 36 24567 100.00 Using index
1 SIMPLE p1_ eq_ref PRIMARY PRIMARY 36 test.p0_.no_product_w2 1 100.00 Using index
1 SIMPLE u3_ ref IDX_A4705D7D9D172915 IDX_A4705D7D9D172915 36 test.p0_.no_product_w2 1 100.00 Using index
1 SIMPLE u2_ const PRIMARY PRIMARY 4 const 1 100.00 Using where; Using index
由分页器生成的查询需要 102 ms !!!?
我在做什么错,为什么要花那么多时间?
计数查询花费这么长时间是正常现象吗?我不敢相信 其他网站正在如何管理分页?
分页的最佳实践是什么。
我已经尝试自己对分页进行计数,并且我做到了:
#Controller:index
$count_all_row = $manager->getRepository(App::getProductClassForGroup($selected_group_code))->countAll()
#Repository
/**
* Count all rows
* @param QueryBuilder|null $queryBuilder If no queryBuilder is provided,a new queryBuilder object is created
* @return int|null Number of rows
* @throws NoResultException
* @throws NonUniqueResultException
*/
public function countAll(?QueryBuilder $queryBuilder = null): ?int
{
$queryBuilder ??= $this->createQueryBuilder($this->_alias,($this->_id) ? $this->_alias . '.' . $this->_id : null);
return $queryBuilder->select('COUNT(1)')->getQuery()->getSingleScalarResult();;
}
它的工作时间约为5.67毫秒,好得多。
5.67 ms
SELECT COUNT(1) AS sclr_0 FROM product_nat p0_
我的查询生成器非常简单,因为我只需要获取表包含的行数即可。
但是现在,如果我需要添加其他参数(例如,按标题搜索产品)或获取价格大于50 $的产品...,则需要修改countAll()
函数,并在我的函数中查找所有结果仓库...
每次修改仅计算标量结果的函数和获取数据结果的函数时,都不是一种好的做法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。