我是一个社交网络,我需要对其进行优化。我搜索并测试(本地)如果我为查询选择字段,我认为我可以赢得30%的性能。 我是对的吗?或者它不会改变?
Actualy当我写一个查询时,我这样写:
public function getNewsfeed($count) {
$q = $this->createQueryBuilder('n')
->leftJoin('n.sender', 'u')
->addSelect('u')
->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')
->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
所以我有两个问题:
感谢您抽出时间抱歉我的新手问题。
答案 0 :(得分:0)
绝对会影响性能。
对于简单/小数据,成本很低。但是,如果您有BLOB
或类似的东西,那么,您可以获得图片 - 服务器只需要时间来获取并将所有数据传输到PHP
。从Doctrine
的角度来看,如果您有相关的实体,则不必浪费额外的时间来创建Proxy
个对象。
如果您希望保留某个模型的对象模型,请使用PARTIAL
,如上所述。
如果您选择不保留对象模型,则可以挤出额外的性能,例如,如果您计划在客户端之后立即发送数据:
$data = $qb->getQuery()->getArrayResult();
缺点是你不能再使用getter / setter了。
术语optimize
与缓存密切相关。鉴于您正在构建社交网络,您是否考虑过使用一个社交网络? :)
答案 1 :(得分:0)
如果你想进行优化我建议使用存储过程并将其映射到ResultSetMapping,并注意我在我的应用程序中实现的有三层的实例:
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);
}
2.-实施
<?php
namespace YourBundle\Entity\Repository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\ResultSetMapping;
class BaseSpRepository extends EntityRepository implements BaseRepositoryInterface
{
public function _getByFilters($sp, ResultSetMapping $rsm, array $vars) {
list($sql, $parameters) = $this->generateArgs($vars, $sp);
$this->clear();
return $this->getEntityManager()
->createNativeQuery($sql, $rsm)
->setParameters($parameters)
->getResult();
}
public function _getOneResult($sp, ResultSetMapping $rsm, array $vars) {
$result = $this->_getByFilters($sp, $rsm, $vars);
if (count($result) < 1) {
return null;
}
return array_shift($result);
}
public function _add($sp, ResultSetMapping $rsm, array $vars) {
$result = array();
list($sql, $parameters) = $this->generateArgs($vars, $sp);
$this->clear();
$result = $this->getEntityManager()
->createNativeQuery($sql, $rsm)
->setParameters($parameters)
->getResult();
if (count($result) == 1)
$result = $result[0];
return $result;
}
public function _update($sp, ResultSetMapping $rsm, array $vars) {
return $this->_add($sp, $rsm, $vars);
}
public function _pages($sp, ResultSetMapping $rsm, array $vars, $size = 10) {
$result = array();
list($sql, $parameters) = $this->generateArgs($vars, $sp);
$this->clear();
$result = $this->getEntityManager()
->createNativeQuery($sql, $rsm)
->setParameters($parameters)
->getResult();
if (count($result) > 0)
$result = array_values($result[0])[0];
if (($result % $size) > 0)
return intval($result / $size) + 1;
return intval($result / $size);
}
public function _recordCnt($sp, ResultSetMapping $rsm, array $vars) {
$result = array();
list($sql, $parameters) = $this->generateArgs($vars, $sp);
$this->clear();
$result = $this->getEntityManager()
->createNativeQuery($sql, $rsm)
->setParameters($parameters)
->getResult();
if (count($result) > 0)
return array_values($result[0])[0];
return 0;
}
public function generateArgs(array $vars, $sql) {
$parameters = array();
$wheres = array();
$sql = sprintf('EXEC %s', $sql);
if (count($vars) > 0) {
$keys = array_keys($vars);
foreach ($keys as $k) {
$wheres[] = sprintf('@%s = :%s', $k, $k);
if ($this->validateDate($vars[$k])) {
$date = new \DateTime(str_replace('/', '-', trim($vars[$k])));
$parameters[$k] = $date;
} else if (preg_match('/^\d+\.?\d{0,2}$/', $vars[$k])) {
$parameters[$k] = floatval(str_replace(',', '.', $vars[$k]));
} else {
$parameters[$k] = $vars[$k];
}
}
$sql = implode(" ", array($sql, implode(",", $wheres)));
}
return array($sql, $parameters);
}
private function validateDate($date, $format = 'd/m/Y') {
$d = \DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
}
3.-如何应用基本模型的示例
<?php
namespace YourBundle\Entity\Repository;
use Doctrine\ORM\Query\ResultSetMapping;
use YourBundle\Entity\Repository\BaseSpRepository;
class DriverRepository extends BaseSpRepository
{
private function getRsm($type = 'a') {
$rsm = new ResultSetMapping();
switch ($type) {
case 'a':
$rsm->addEntityResult('YourBundle\Entity\Driver', 'd');
$rsm->addFieldResult('d', 'driverId', 'id');
$rsm->addFieldResult('d', 'dni', 'dni');
$rsm->addFieldResult('d', 'names', 'names');
$rsm->addFieldResult('d', 'lastNames', 'lastNames');
$rsm->addFieldResult('d', 'license', 'license');
$rsm->addFieldResult('d', 'register', 'register');
$rsm->addFieldResult('d', 'revalidationAt', 'revalidationAt');
$rsm->addJoinedEntityResult('YourBundle\Entity\LicenseCategory', 'lc', 'd', 'licenseCategory');
$rsm->addFieldResult('lc', 'licenseCategoryId', 'id');
$rsm->addFieldResult('lc', 'licenseCategoryName', 'name');
$rsm->addJoinedEntityResult('YourBundle\Entity\Provider', 'p', 'd', 'provider');
$rsm->addFieldResult('p', 'providerId', 'id');
$rsm->addFieldResult('p', 'providerName', 'name');
break;
case 'b':
$rsm->addEntityResult('YourBundle\Entity\Driver', 'd');
$rsm->addScalarResult('recordCnt', 'd');
break;
case 'c':
$rsm->addEntityResult('YourBundle\Entity\Driver', 'd');
$rsm->addFieldResult('d', 'id', 'id');
$rsm->addFieldResult('d', 'dni', 'dni');
$rsm->addFieldResult('d', 'license', 'license');
$rsm->addFieldResult('d', 'register', 'register');
break;
}
return $rsm;
}
public function getByFilters(array $vars = array()) {
return $this->_getByFilters("usp_drivers_index", $this->getRsm(), $vars);
}
public function getOneResult(array $vars = array()) {
return $this->_getOneResult("usp_drivers_index", $this->getRsm(), $vars);
}
public function add(array $vars = array()) {
return $this->_add("usp_drivers_add", $this->getRsm(), $vars);
}
public function update(array $vars = array()) {
return $this->_update("usp_drivers_edit", $this->getRsm(), $vars);
}
public function pages(array $vars = array(), $size = 10) {
return $this->_pages("usp_drivers_record_count", $this->getRsm('b'), $vars, $size);
}
public function exist(array $vars = array()) {
return $this->_getByFilters("usp_drivers_check_if_exist", $this->getRsm('c'), $vars);
}
}