Join 嵌套多个连接
我正试图用条令优化symfony应用程序。我偶然发现了以下问题: 在视图中,我使用了$project->getProgress();但是这样做会随着项目的增多而增加查询的数量。所以我尝试用左连接将进度放入projects查询(覆盖findAll方法),但没有成功。查询的数量实际上增加了Join 嵌套多个连接,join,symfony1,doctrine,Join,Symfony1,Doctrine,我正试图用条令优化symfony应用程序。我偶然发现了以下问题: 在视图中,我使用了$project->getProgress();但是这样做会随着项目的增多而增加查询的数量。所以我尝试用左连接将进度放入projects查询(覆盖findAll方法),但没有成功。查询的数量实际上增加了 public function findAll($hydrationMode = null) { $q = $this->createQuery('p') -
public function findAll($hydrationMode = null)
{
$q = $this->createQuery('p')
->leftJoin('p.progress pr')
->leftJoin('pr.sfGuardUser u')
->leftJoin('p.raws r')
->leftJoin('p.series');
return $q->execute(array(), $hydrationMode);
}
这就是我试图用尽可能少的查询量创建的结果:
array() {
[0]=>
array() {
["id"]=> string(1) "1"
...
["progress"]=>
array() {
array() {
array() { progress1 }
array() { progress2 }
array() { progress3 }
....
}
}
}
我查阅了symfony和Doctrine的文档,没有找到我的答案。我也在谷歌上搜索了很长一段时间。(几个月来我一直在寻找解决方案)我希望我已经把我的问题描述得足够好了
schema.yml:
projects:
actAs:
Timestampable: ~
columns:
user_id: integer(4)
series_id: bigint
pages: int
chapter: string
translators_id: bigint
proofreaders_id: bigint
cleaners_id: bigint
typesetters_id: bigint
raws_id: bigint
hide_project: bool
complete: bool
relations:
sfGuardUser:
local: user_id
foreign: id
onDelete: CASCADE
series:
local: series_id
foreign: id
type: one
foreignType: many
onDelete: CASCADE
progress:
local: id
foreign: projects_id
onDelete: CASCADE
type: one
foreignType: many
projectsProgress:
actAs: [Timestampable]
columns:
projects_id: bigint
user_id: integer(4)
job:
type: enum
notnull: true
values: [tl,pr,cl,ts]
beginpage: int
endpage: int
complete: bool
file: string
url: clob
relations:
sfGuardUser:
local: user_id
foreign: id
onDelete: CASCADE
projects:
local: projects_id
foreign: id
onDelete: CASCADE
foreignAlias: progress
您需要修改获取
项目
对象的查询以包含联接。通常,获取Project
对象的查询应该放在ProjectTable
中
如果要修改
Project
的所有查询或查询子集,请查看。使用水合物模式的问题是,您可能会获取不使用的数据。我真的不知道如何获取所有数据,但假设每个项目都会带来所有必需的数据,至少再添加一个查询
对于复杂查询(和优化),我更喜欢手动查询,并在一个查询中管理所有需要的数据,例如:
$query = "SELECT ... FROM projects p LEFT JOIN progress pr (LEFT JOIN sfGuardUser u (LEFT JOIN...) ON pr.user_id = u.id ) ON p.id = pr.projects_id"
$rs = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query);
是一个包含选定数据的数组。拥有所有数据后,您可以随心所欲地创建一个数组,但请记住,这样您只需执行一次查询(减少数据库负载),但需要添加一些时间机器来解析数组。如果修改查询,查询量将从17增加到253。进度的子集总是空的。我通过如下方式重写代码,成功地将加载时间减少了100-150毫秒:这是最好的方法还是有更好的方法?我正在阅读代码。我们在谈论多少个项目?因为通过这种方式,您可以将db负载转移到解析负载,并且您可能没有使用所有项目(如果是,请过滤它们)。有时最好多一些查询,少一些解析,但始终取决于有多少数据。例如,您可以执行两个查询:一个带来项目数据(if块),另一个带来进度和raws数据。优化查询的方法是减少联接表。我看过你的密码了。我们正在谈论1到20个开放项目,我需要所有的项目,因为这个页面是一个列表,显示了每个开放项目的进展。(忘记添加where条件以过滤已完成的内容)当前页面的加载时间现在是450毫秒。我将尝试使用您的代码,sql有一些问题需要修复。我将比较这两个函数的加载时间。这两个函数都需要大约38ms才能完成,这比以前快得多。谢谢你知道如何加快观看速度吗?这是唯一能让一切变慢的东西。(无法缓存,因为数据是动态的)很好:)我认为加快视图速度的唯一方法是减少foreach的*、*if等,使其尽可能简单。仅加载将要使用的js并减少图像大小。有很多提高网站速度的最佳实践,只需使用google:)例如check