Symfony 选择字段以优化查询的最佳方法

Symfony 选择字段以优化查询的最佳方法,symfony,doctrine-orm,Symfony,Doctrine Orm,我有一个社交网络,我需要优化它。我搜索并测试了(本地)我认为如果我为我的查询选择字段,我可以赢得30%的性能

我有一个社交网络,我需要优化它。我搜索并测试了(本地)我认为如果我为我的查询选择字段,我可以赢得30%的性能<我说得对吗?或者它不会改变?

<?php

namespace YourBundle\Entity\Repository;

use Doctrine\ORM\Query\ResultSetMapping;

interface BaseRepositoryInterface 
{
    public function _getByFilters($sp, ResultSetMapping $rsm, array $vars);

    public function _getOneResult($sp, ResultSetMapping $rsm, array $vars);

    public function _add($sp, ResultSetMapping $rsm, array $vars);

    public function _update($sp, ResultSetMapping $rsm, array $vars);

    public function _recordCnt($sp, ResultSetMapping $rsm, array $vars);

    public function _pages($sp, ResultSetMapping $rsm, array $vars, $size);

    public function generateArgs(array $vars, $sql);
}
实际上,当我写查询时,我是这样写的:

public function getNewsfeed($count) {

    $q = $this->createQueryBuilder('n')
                ->leftJoin('n.sender', 'u')
                    ->addSelect('u')
                ->orderBy('n.id', 'DESC')
                ->setMaxResults($count);

    return $q->getQuery()->getResult();
}
public function getNewsfeed($count) {

    $q = $this->createQueryBuilder('n')
                ->select('partial n.{id, type, reference, data, date}')
                ->leftJoin('n.sender', 'u')
                    ->addSelect('partial u.{id, name, avatar, roles, sex, last_activity, suspended}')
                ->orderBy('n.id', 'DESC')
                ->setMaxResults($count);

    return $q->getQuery()->getResult();
}
所以,给我这个:

SELECT n0_.id AS id0, n0_.type AS type1, n0_.data AS data2, n0_.reference AS reference3, n0_.date AS date4, f1_.username AS username5, f1_.username_canonical AS username_canonical6, f1_.email AS email7, f1_.email_canonical AS email_canonical8, f1_.enabled AS enabled9, f1_.salt AS salt10, f1_.password AS password11, f1_.last_login AS last_login12, f1_.locked AS locked13, f1_.expired AS expired14, f1_.expires_at AS expires_at15, f1_.confirmation_token AS confirmation_token16, f1_.password_requested_at AS password_requested_at17, f1_.roles AS roles18, f1_.credentials_expired AS credentials_expired19, f1_.credentials_expire_at AS credentials_expire_at20, f1_.id AS id21, f1_.user_ip AS user_ip22, f1_.name AS name23, f1_.avatar AS avatar24, f1_.birthday AS birthday25, f1_.sex AS sex26, f1_.city AS city27, f1_.country AS country28, f1_.last_activity AS last_activity29, f1_.warning AS warning30, f1_.status AS status31, f1_.notification AS notification32, f1_.visitor AS visitor33, f1_.friend AS friend34, f1_.message AS message35, f1_.antiflood AS antiflood36, f1_.wantmail AS wantmail37, f1_.autodestruction AS autodestruction38, f1_.suspended AS suspended39, n0_.sender_id AS sender_id40, f1_.profil_id AS profil_id41 FROM newsfeed n0_ LEFT JOIN fos_user f1_ ON n0_.sender_id = f1_.id ORDER BY n0_.id DESC LIMIT 15
你可以看到,它很长。我不需要电子邮件、密码等。我在Stack上搜索了如何使用条令选择字段,以及工作人员的唯一方法如下:

public function getNewsfeed($count) {

    $q = $this->createQueryBuilder('n')
                ->leftJoin('n.sender', 'u')
                    ->addSelect('u')
                ->orderBy('n.id', 'DESC')
                ->setMaxResults($count);

    return $q->getQuery()->getResult();
}
public function getNewsfeed($count) {

    $q = $this->createQueryBuilder('n')
                ->select('partial n.{id, type, reference, data, date}')
                ->leftJoin('n.sender', 'u')
                    ->addSelect('partial u.{id, name, avatar, roles, sex, last_activity, suspended}')
                ->orderBy('n.id', 'DESC')
                ->setMaxResults($count);

    return $q->getQuery()->getResult();
}
给我一个小问题:

SELECT n0_.id AS id0, n0_.type AS type1, n0_.data AS data2, n0_.reference AS reference3, n0_.date AS date4, f1_.roles AS roles5, f1_.id AS id6, f1_.name AS name7, f1_.avatar AS avatar8, f1_.sex AS sex9, f1_.last_activity AS last_activity10, f1_.suspended AS suspended11, n0_.sender_id AS sender_id12, f1_.profil_id AS profil_id13 FROM newsfeed n0_ LEFT JOIN fos_user f1_ ON n0_.sender_id = f1_.id ORDER BY n0_.id DESC LIMIT 15
所以我有两个问题:

  • 如果我选择字段,我真的会赢得很多性能
  • 这是最好的方式吗?或者您有另一种选择字段的方法

  • 感谢您的时间,并为我的新手问题感到抱歉。

    这肯定会影响性能

    对于简单/小型数据,成本最低。然而,如果您有
    BLOB
    s或类似的东西,那么您就得到了图片服务器,它只需要时间来获取所有数据并将其传输到
    PHP
    。从
    原则
    的角度来看,如果您有相关的实体,您不必浪费额外的时间来创建
    代理
    对象

    如果您希望为某些模型保留对象模型,请像上面那样使用
    PARTIAL

    如果您选择不保留对象模型,例如,如果您计划在以下情况下立即将数据发送到客户端,则可以压缩额外的性能:

    $data = $qb->getQuery()->getArrayResult();
    
    缺点是你不能再使用getter/setter了

    旁注:
    术语
    optimize
    与缓存密切相关。考虑到你正在建立一个社交网络,你是否考虑过使用它

    如果您想要优化,我建议使用存储过程并将其与ResultsMapping进行映射,请注意,在本例中,我在应用程序中实现了三个层:

    1.-接口

    <?php
    
    namespace YourBundle\Entity\Repository;
    
    use Doctrine\ORM\Query\ResultSetMapping;
    
    interface BaseRepositoryInterface 
    {
        public function _getByFilters($sp, ResultSetMapping $rsm, array $vars);
    
        public function _getOneResult($sp, ResultSetMapping $rsm, array $vars);
    
        public function _add($sp, ResultSetMapping $rsm, array $vars);
    
        public function _update($sp, ResultSetMapping $rsm, array $vars);
    
        public function _recordCnt($sp, ResultSetMapping $rsm, array $vars);
    
        public function _pages($sp, ResultSetMapping $rsm, array $vars, $size);
    
        public function generateArgs(array $vars, $sql);
    }
    

    是的,我想我必须为细枝模板保留对象。我已经缓存了常用块:最后一个用户、最后一个论坛主题,但其余的我无法缓存:论坛、聊天、即时消息(pv)、成员搜索、profil、评论、新闻提要等。如果我没有弄错的话,您不需要为了在
    细枝中呈现数据而保留对象模型