Phalcon 性能相关查询
Phalcon performance related queries
我正在为端点/项目的输出构建一个 REST API 我已经创建了 2 个模型:
项目:
class Projects extends BaseModel
{
public function initialize()
{
$this->hasMany('id', 'Participants', 'projectId');
}
}
参与者:
class Participants extends BaseModel
{
public function initialize()
{
$this->belongsTo('projectId', 'Projects', 'id');
}
}
比方说,我有 10 个项目:(1 个查询)
$results = Projects::find();
我遍历所有 10 个,但我也想要所有参与者:
foreach($results as $result) {
echo $result->participants; // 1 query
}
所以在循环结束时 Phalcon 对每个项目进行了额外的查询。
这些查询是通过在迭代 10 个项目时访问 $result->participants 进行的:
SELECT IF(COUNT(*)>0, 1 , 0) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_NAME`='projects'
DESCRIBE `projects`
SELECT `projects`.`id`, `projects`.`title`, `projects`.`client`, `projects`.`color`, `projects`.`start_date`, `projects`.`end_date`, `projects`.`notes`, `projects`.`stateId`, `projects`.`created_at`, `projects`.`updated_at` FROM `projects`
SELECT IF(COUNT(*)>0, 1 , 0) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_NAME`='project_participants'
DESCRIBE `project_participants`
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
问题
有没有办法预先查询关系,所以它会是一个查询。
当我使用 Phalcon 提供的查询生成器时,我无法以相同的方式访问 ->participants。
编辑
我最终使用了查询生成器,为所有列命名空间
$builder = $modelsManager->createBuilder();
$builder->columns($columns)
->from('Projects')
->leftJoin('Participants')
->getQuery()
->execute();
像这样的列:
Projects.id as projects_id
...
Participants.id as participants_id
Participants.projectId as participants_projectId
因为在查询生成器创建的结果上访问 ->participants,所以也进行了额外的查询。
要使用 QueryBuilder 以相同的方式访问 ->participants,您必须将连接构建到 Query 中。
代码示例可能类似于:
$queryBuilder = $this->getDI()->getModelsManager()
->createBuilder()
->columns(['p.id','participants.*'])
->addFrom('Entity\Projects', 'p')
->leftJoin('Entity\Participants', 'participants.projectId = p.id', 'participants')
->groupBy('p.id, participants.id')
->orderBy('p.id ASC');
$resultSet = $queryBuilder->getQuery()->execute();
groupBy()
by 用于使结果可能是多维的。
这种查询(在 PgSQL 下测试)使 Phalcon 在项目 p
.
的结果集中创建参与者 pi
的一些后续结果集对象
您仍然可以使用 foreach()
遍历它,但毕竟,我不确定它是否减少了最终查询计数。
解雇 $result = $resultSet->toArray()
使 $result['pi']
仍然是结果集,所以你应该对此保持谨慎。 您可以通过在 columns()
参数中定义确切的列来强制将其转储为数组。 它有其缺点 - 您将不再从 groupBy()
中获利,至少Phalcon 1.3.2 和 PHP 5.5.3 在 运行 此处。
Phalcon 上有一个很棒的预加载库。
stibiumz phalcon eager loading
该库解决了 N + 1 个关系查询。它已经包含在 phalcon 孵化器中。我已经在生产中使用它了。
它的作用是使用 IN 子句创建一个查询并用结果填充模型。
在 a 上有很多:
SELECT * FROM main
SELECT * FROM related WHERE x.id IN (results from the previous resultset)
我正在为端点/项目的输出构建一个 REST API 我已经创建了 2 个模型:
项目:
class Projects extends BaseModel
{
public function initialize()
{
$this->hasMany('id', 'Participants', 'projectId');
}
}
参与者:
class Participants extends BaseModel
{
public function initialize()
{
$this->belongsTo('projectId', 'Projects', 'id');
}
}
比方说,我有 10 个项目:(1 个查询)
$results = Projects::find();
我遍历所有 10 个,但我也想要所有参与者:
foreach($results as $result) {
echo $result->participants; // 1 query
}
所以在循环结束时 Phalcon 对每个项目进行了额外的查询。
这些查询是通过在迭代 10 个项目时访问 $result->participants 进行的:
SELECT IF(COUNT(*)>0, 1 , 0) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_NAME`='projects'
DESCRIBE `projects`
SELECT `projects`.`id`, `projects`.`title`, `projects`.`client`, `projects`.`color`, `projects`.`start_date`, `projects`.`end_date`, `projects`.`notes`, `projects`.`stateId`, `projects`.`created_at`, `projects`.`updated_at` FROM `projects`
SELECT IF(COUNT(*)>0, 1 , 0) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_NAME`='project_participants'
DESCRIBE `project_participants`
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
SELECT `project_participants`.`id`, `project_participants`.`project_id`, `project_participants`.`user_id`, `project_participants`.`user_role_id`, `project_participants`.`user_state_id`, `project_participants`.`updated_at`, `project_participants`.`created_at` FROM `project_participants` WHERE `project_participants`.`project_id` = :0
问题
有没有办法预先查询关系,所以它会是一个查询。 当我使用 Phalcon 提供的查询生成器时,我无法以相同的方式访问 ->participants。
编辑
我最终使用了查询生成器,为所有列命名空间
$builder = $modelsManager->createBuilder();
$builder->columns($columns)
->from('Projects')
->leftJoin('Participants')
->getQuery()
->execute();
像这样的列:
Projects.id as projects_id
...
Participants.id as participants_id
Participants.projectId as participants_projectId
因为在查询生成器创建的结果上访问 ->participants,所以也进行了额外的查询。
要使用 QueryBuilder 以相同的方式访问 ->participants,您必须将连接构建到 Query 中。
代码示例可能类似于:
$queryBuilder = $this->getDI()->getModelsManager()
->createBuilder()
->columns(['p.id','participants.*'])
->addFrom('Entity\Projects', 'p')
->leftJoin('Entity\Participants', 'participants.projectId = p.id', 'participants')
->groupBy('p.id, participants.id')
->orderBy('p.id ASC');
$resultSet = $queryBuilder->getQuery()->execute();
groupBy()
by 用于使结果可能是多维的。
这种查询(在 PgSQL 下测试)使 Phalcon 在项目 p
.
pi
的一些后续结果集对象
您仍然可以使用 foreach()
遍历它,但毕竟,我不确定它是否减少了最终查询计数。
解雇 $result = $resultSet->toArray()
使 $result['pi']
仍然是结果集,所以你应该对此保持谨慎。 您可以通过在 columns()
参数中定义确切的列来强制将其转储为数组。 它有其缺点 - 您将不再从 groupBy()
中获利,至少Phalcon 1.3.2 和 PHP 5.5.3 在 运行 此处。
Phalcon 上有一个很棒的预加载库。
stibiumz phalcon eager loading
该库解决了 N + 1 个关系查询。它已经包含在 phalcon 孵化器中。我已经在生产中使用它了。
它的作用是使用 IN 子句创建一个查询并用结果填充模型。
在 a 上有很多:
SELECT * FROM main
SELECT * FROM related WHERE x.id IN (results from the previous resultset)