nag*_*dev 5 mysql sql doctrine symfony symfony4
我有一个需要分页的表(没有关系)。为此,我使用 Doctrine 分页工具。
该表包含 634484 条记录。Doctrine 执行以下查询:
SELECT p0_.id AS id_0, p0_.name AS name_1, p0_.level AS level_2, p0_.alignment AS alignment_3, p0_.account_id AS account_id_4 FROM player.player p0_ ORDER BY p0_.level DESC LIMIT 25;
Run Code Online (Sandbox Code Playgroud)
解释:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE p0_ index search 1 25 100.00
Run Code Online (Sandbox Code Playgroud)
执行时间:1.04 ms
有问题的查询:
SELECT
COUNT(*) AS dctrn_count
FROM
(
SELECT
DISTINCT id_0
FROM
(
SELECT
p0_.id AS id_0,
p0_.name AS name_1,
p0_.level AS level_2,
p0_.alignment AS alignment_3
FROM
player.player p0_
ORDER BY
p0_.level DESC
) dctrn_result
) dctrn_table
Run Code Online (Sandbox Code Playgroud)
解释:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL 634484 100.00
2 DERIVED p0_ ALL PRIMARY 634484 100.00 Using temporary
Run Code Online (Sandbox Code Playgroud)
执行时间:2414.72 ms
Doctrine 使用 DISTINCT 关键字来找出表包含多少行,这可能是查询运行这么长时间的原因。
没有 DISTINCT 关键字的执行时间:1.26 ms
编辑:
存储库:
public function findLatestPaginated(int $page = 1): array
{
$queryBuilder = $this->createQueryBuilder('c')
->addOrderBy('c.level', 'DESC');
return $this->paginate($queryBuilder, $page, Character::PER_PAGE);
}
Run Code Online (Sandbox Code Playgroud)
分页方法:
<?php
namespace App\Core\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository as BaseServiceEntityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator;
abstract class ServiceEntityRepository extends BaseServiceEntityRepository
{
protected function paginate(QueryBuilder $queryBuilder, int $currentPage, int $perPage)
{
$currentPage = $currentPage < 1 ? 1 : $currentPage;
$firstResult = ($currentPage - 1) * $perPage;
/** @var Query $query */
$query = $queryBuilder
->setFirstResult($firstResult)
->setMaxResults($perPage)
->getQuery();
$paginator = new Paginator($query, false);
$numResults = $paginator->count();
$hasPreviousPage = $currentPage > 1;
$hasNextPage = ($currentPage * $perPage) < $numResults;
return [
'result' => $paginator->getIterator(),
'currentPage' => $currentPage,
'hasPreviousPage' => $hasPreviousPage,
'hasNextPage' => $hasNextPage,
'previousPage' => $hasPreviousPage ? $currentPage - 1 : null,
'nextPage' => $hasNextPage ? $currentPage + 1 : null,
'numPages' => (int)ceil($numResults / $perPage),
'haveToPaginate' => $numResults > $perPage,
];
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
id这是主键)您可以通过执行以下操作从计数查询中禁用DISTINCT关键字:
use Doctrine\ORM\Tools\Pagination\CountWalker;
$query->setHint(CountWalker::HINT_DISTINCT, false);
Run Code Online (Sandbox Code Playgroud)
看看Doctrine/ORM/Tools/Pagination/Paginator代码,这似乎会阻止将重复语句添加到计数查询中。
| 归档时间: |
|
| 查看次数: |
3771 次 |
| 最近记录: |