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)