Zend Framework 2 Doctrine MongoDB ODM and Apache too slow


Zend Framework 2 Doctrine MongoDB ODM and Apache too slow

我们在运行时遇到了奇怪的性能问题

  • PHP 5.5.18-1上的Zend Framework 2.3.3
  • Doctrine MongoDB ODM模块(https://github.com/doctrine/mongodb,https://github.com/doctrine/DoctrineMongoODMModule)
  • Ubuntu 12.04上的VirtualBox通过Vagrant(https://vagrantcloud.com/hashicorp/boxes/precise64)

我们确信这是一个而不是数据库问题(在一个真实的MongoDB实例中尝试过,结果仍然相同)。


场景

我们已经定义了以类似于以下方式与条令ODM一起工作的对象:

<?php
namespace CatalogueManager'Document;
use Doctrine'ODM'MongoDB'Mapping'Annotations as ODM;
use Doctrine'Common'Collections'ArrayCollection;
/*
 * @ODM'Document(repositoryClass="CatalogueManager'Repository'ProductRepository")
 */
class Item
{
    /** @ODM'Id */
    protected $id;
    /** @ODM'String */
    protected $name;
    /** @ODM'Timestamp */
    protected $created;
    /** @ODM'Timestamp */
    protected $updated;
    // ---------------------------------------------------------------------- //
    /**
     * Return properties as an array. Helper method to assist with converting
     * doctrine objects to arrays so we can return front-end api calls as json.
     *
     * Required as currently Doctrine ODM do not support array hydration of
     * referenced documents.
     *
     * @access public
     * @return array
     *
     */
    public function toArray()
    {
        $arr = ['id'          => $this->id,
                'name'        => $this->name,
                'urlSlug'     => $this->urlSlug,
                'desc'        => $this->desc,
                'metaData'    => $this->metadata,
                'category'    => $this->category,
                'brand'       => $this->brand,
                'assets'      => $this->assets,
                'shipping'    => $this->shipping,
                'specs'       => $this->specs,
                'attrs'       => $this->attrs,
                'optionTypes' => $this->optionTypes
                ];
        return $arr;
    }
    // ---------------------------------------------------------------------- //
    /**
     * Getter
     *
     * @access public
     * @return string
     *
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Getter
     *
     * @access public
     * @return string
     *
     */
    public function getName()
    {
        return $this->name;
    }
    // ---------------------------------------------------------------------- //
    /**
     * Setter
     *
     * @param string $value Property value
     *
     * @access public
     * @return void
     *
     */
    public function setName($value)
    {
        $this->name = $value;
    }
}

我们正在使用它们将大约100种产品导入到产品数据库中。这一切在真实机器上大约需要5秒,但在虚拟机上尝试时,做同样的事情大约需要25秒。

看起来问题可能是Apache,在处理这一切的过程中,它占用了99%的负载。但我很难确定到底发生了什么。

任何建议都将不胜感激。。。


更新

这似乎只在写入数据时才会发生。读取数据似乎还可以。

可用的Webgrind数据(屏幕截图):https://www.dropbox.com/s/jjlg7ano6epy6t1/webgrind.png?dl=0

在查看了XDebug数据的一些屏幕截图后,我认为您只是以错误的方式使用了ORM/ODM,因为您正在批量处理>13K的结果。

有关此类操作的正确解决方案,请参阅http://doctrine-orm.readthedocs.org/en/latest/reference/batch-processing.html

发生的事情很简单:-ODM从数据库加载一条记录-ODM将该记录存储到CCD_ 1中-在flush中,ODM迭代UnitOfWork中的所有条目,查找更改的文档/实体

如果在UnitOfWork中继续存储更多的数据,那么很明显,每次重复操作时迭代将花费更长的时间。

您应该在正在处理的批块之间调用ObjectManager#clear()

所以这不是一个答案,我将寻求建议。在本地机器上运行速度较慢是正常的,更不用说在虚拟机器上了。

可能有帮助的事情:

  1. 您可以通过将其添加到流浪文件中,使虚拟机具有更多内存

config.vm.provider "virtualbox" do |v| v.customize ["modifyvm", :id, "--memory", "1024"] end

  1. 还可以使用zf2模块ZendDeveloperTools,它将显示您的请求、分组、数据库查询(它与条令一起工作)的时间以及不需要的时间。你可以精确定位任何运行缓慢的东西

只是一个旁注。为什么在12.04上运行php5.5,为什么不在14.04上运行(它更可靠,但不那么精确)。设置起来更容易。