And*_*erj 7 pagination subquery query-builder database-performance doctrine-orm
我有一个大查询(在我的查询构建器中)和很多左连接.所以我得到他们的评论和标签等文章.假设我有以下dql:
$dql = 'SELECT blogpost, comment, tags
FROM BlogPost blogpost
LEFT JOIN blogpost.comments comments
LEFT JOIN blogpost.tags tags';
Run Code Online (Sandbox Code Playgroud)
现在让我们说我的数据库有超过100个博客帖子,但我只想要前10个,但是包含那些10及其所有标签的所有评论,如果它们存在的话.如果我使用setMaxResults它限制行.所以我可能得到前两个帖子,但最后一个帖子缺少一些评论或标签.所以跟随不起作用.
$result = $em->createQuery($dql)->setMaxResults(15)->getResult();
Run Code Online (Sandbox Code Playgroud)
使用doctrine2.2附带的几乎没有文件记录的分页解决方案对我来说并不是真的有效,因为它太慢了,我也可以加载所有数据.
我在Stackoverflow文章中尝试了解决方案,但即使该文章仍然缺少最佳实践,所提出的解决方案也非常慢.
对于如何做到这一点,是否有最佳实践?没有人在生产模式下使用Doctrine2.2吗?
Bar*_*zyn 11
使用这样的查询获得正确的结果是有问题的.Doctrine网站上有一个教程解释了这个问题.
本教程更多的是关于分页而不是获得前5个结果,但总的想法是你需要做一个"SELECT DISTINCT a.id FROM articles a ... LIMIT 5"而不是普通的SELECT.它比这复杂一点,但该教程的最后两点应该让你走上正轨.
更新:
这里的问题不是Doctrine或任何其他ORM.问题在于数据库能够返回您要求的结果.这就是加入工作的方式.
如果对查询执行EXPLAIN,它将为您提供有关正在发生的事情的更深入的答案.将结果添加到您的初始问题中是个好主意.
基于分页文章中讨论的内容,您似乎需要至少2个查询才能获得所需的结果.将DISTINCT添加到查询中可能会大大减慢查询速度,但只有在您加入查询时才真正需要它.您可以编写另一个查询,只检索按创建日期排序的前10个帖子,而不加入连接.获得这10个帖子的ID后,请使用您的联接进行另一个查询,然后执行WHERE blogpost.id IN (...) ORDER BY blogpost.created
.这种方法应该更有效率.
SELECT
bp
FROM
Blogpost bp
ORDER BY
bp.created DESC
LIMIT 10
Run Code Online (Sandbox Code Playgroud)
由于您在第一个查询中所关心的只是ID,因此可以将Doctrine设置为使用Scalar Hydration.
SELECT
bg
FROM
Blogpost bp
LEFT JOIN
bp.comments c
LEFT JOIN
bp.tags t
WHERE
bp.id IN (...)
ORDER BY
bp.created DESC
Run Code Online (Sandbox Code Playgroud)
您也可以使用相关子查询在一个查询中执行此操作.子查询总是坏的神话不是真的.有时它们比连接更快.您需要尝试找出最适合您的解决方案.
归档时间: |
|
查看次数: |
5761 次 |
最近记录: |