首次使用数组很慢

时间:2016-06-03 15:43:24

标签: php sql arrays typo3 extbase

我遇到了一个奇怪的错误"在PHP中,因为我知道我是新手。

我正在开发一个TYPO3扩展,它对数据有一些重大的性能问题,或者我认为。 事实证明,第一次使用数组,它存储了我从数据库查询中获得的所有对象,正在逐渐取消。 之后的每次使用或循环都会很快。

代码如下所示:

        $productsArr = $this->productRepository->findByDetail($category, $properties);

        $newSortArr = array();
        $familyProductList = array();

        $counter = count($productsArr);
        /** @var Product $product */
        for($i = 0; $i < $counter; $i++) {

            //it takes to long to do this
            $product = $productsArr[$i];

            if(!empty($productsArr[$i])) {
                $newSortArr[$product->getInFamily()->getUid()][] = $product;
            }
        }

我首次使用对象数组的位置并不重要。首次使用阵列总是需要大约30秒。

有没有人遇到过类似的东西? 如果您需要更多信息,我很乐意提供。

提前致谢!

3 个答案:

答案 0 :(得分:3)

您的$productsArr不是数组,而是Exbase的类QueryResult的对象,您可以使用foreach进行迭代或进行索引访问。此Object仅在需要时执行查询并构建其对象,因此,当您执行$product = $productsArr[$i];时,Product的所有$productsArr - 对象都会构建。主要的问题是在PHP中构建对象的性能不佳并占用大量内存。

因此,为避免性能问题,请考虑使用

自定义查询
$this->productRepository->createQuery()->statement('select * from ...')->execute();

获取您想要的内容,而不是加载大量对象,稍后在PHP中对其进行优化。

答案 1 :(得分:1)

正如杰伊已经提到的,你的结果不是数组,而是QueryResult。仅供参考,可以通过在查询末尾添加->toArray()将其转换为数组:

$productsArr = $this->productRepository->findByDetail($category, $properties)->toArray();

但这不会改善情况。有两个可能的问题:

迭代所有对象

QueryResult的优势在于它仅反映查询的结果,但尚未解析所有对象。可以传递QueryResult,例如到分页小部件,然后只加载请求的结果(e.h.1-10,11-20等)。

由于您正在应用手动排序,因此会加载所有对象(取决于您的项目,这可能很多......)。

显然您想按家庭UID对产品进行分类?为什么不在ProductRepository

中使用Extbase功能
protected $defaultOrderings = array(
    'inFamily.uid' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
);

急切加载子对象

您的模型Product可能与其他模型有关(e.h.产品到类别,产品到选项等)。默认情况下,Extbase会在访问对象时解析所有这些关系。

为了防止这种情况,您可以使用延迟加载来实现关系。这对于未在所有视图中使用的子对象都有意义。例如。在列表视图中,您只需要产品的标题,图片和价格,但您不需要该产品的所有选项。

要为这些子对象配置延迟加载,您只需在模型中添加@lazy注释:

/**
 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\My\Extension\Domain\Model\ObjectStorageModel>
 * @lazy
 */
protected $categories;

/**
 * @var \My\Extension\Domain\Model\OtherModel
 * @lazy
 */
protected $author;

延迟加载可能有一些缺点,例如:在某些情况下,当检查对象是OtherModel的实例时,您会得到类型为LazyLoadingProxy的对象。您可以解决大多数这些问题,或者在正常情况下甚至可能无法解决这些问题。如果你真的依赖于一个不是LazyLoadingProxy的对象的常见解决方法是这样的检查:

if ($product->getAuthor() instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) {
    $product->getAuthor()->_loadRealInstance();
}

这确保无论如何你都拥有一个真实的&#34;对象的实例。

当您针对其中一个问题进行更改时,请不要忘记刷新系统缓存。

答案 2 :(得分:0)

我假设数组填充在第一行。您是否考虑过使用$product填充foreach($productArr as $product)而不是使用for