首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Shopware 6导入性能

Shopware 6导入性能
EN

Stack Overflow用户
提问于 2022-08-08 07:31:35
回答 1查看 237关注 0票数 0

我需要同步产品与ERP,它给我们的产品数据,没有三角洲,每天晚上。所以,我做了一个导入脚本,它实际上运行良好,但它使用的是年龄。有大约2000种产品,所以它不应该花那么长时间,但它需要大约7个小时!我确实要删除产品属性的关联,也要删除丢失的产品,但7小时的时间还是太长了。服务器是可伸缩的可扩展服务器,内存高达8GB。

以下是代码(简化):

代码语言:javascript
复制
    /*
     * Amount of entities to execute per round.
     * */
    public const BATCH = 200;

    public function execute()
    {
        // read products from import xml file
        $importProducts = $this->loadProducts();
        $csvBatch = array_chunk($importProducts, self::BATCH);
        $productNumbers = [];

        foreach ($csvBatch as $products) {
            $productNumbers[] = $this->processImportProducts($products, false);
        }

        $this->deleteProducts(array_merge(...$productNumbers));

        return 0;
    }

    private function processImportProducts($productsData)
    {
        $products = [];
        $productNumbers = [];

        foreach ($productsData as $product) {
            $products[$product['ProductNo']] = $this->importProducts($product);
            $productNumbers[] = $product['ProductNo'];
        }

        // upsert product
        try {
            $this->cleanProductProperties($products, $this->context);
            $this->productRepository->upsert(array_values($products), $this->context);
        } catch (WriteException $exception) {
            $this->logger->info(' ');
            $this->logger->info('<error>Products could not be imported. Message: '. $exception->getMessage() .'</error>');
        }
        unset($products);

        return $productNumbers;
    }


    private function cleanProductProperties($products, $context)
    {
        $productIds = array_values(array_map(static function($product){
            return $product['id'];
        }, $products));

        $productProperties = $this->productPropertyRepository->searchIds(
            (new Criteria())->addFilter(new EqualsAnyFilter('productId', $productIds)),
            $context
        );

        $productRelationsToDelete = [];
        foreach($productProperties->getIds() as $productProperty) {
            $productRelationsToDelete[] = [
                'productId' => $productProperty['product_id'],
                'optionId' => $productProperty['property_group_option_id']
            ];
        }

        $this->productPropertyRepository->delete($productRelationsToDelete, $context);

        unset($productIds, $productProperties, $productRelationsToDelete);
    }

    private function importProducts($product)
    {
        // search product by productNumber
        $productSearch = $this->productRepository->search(
            (new Criteria())->addFilter(new EqualsFilter('productNumber', $productNumber)),
            $this->context
        );

        $existingProduct = $productSearch->getEntities()->first();
        if ($existingProduct) {
            $productId = $existingProduct->getId();
        } else {
            $productId = Uuid::randomHex();
        }

        $productData = [
            'id' => $productId,
            'productNumber' => $productNumber,
            'price' => [
                [
                    'currencyId' => Defaults::CURRENCY,
                    'gross' => 0,
                    'net' => 0,
                    'linked' => true
                ]
            ],
            'stock' => 99999,
            'taxId' => $this->taxId,
            'name' => $productNames,
            'description' => $productDescriptions
        ];

        return $productData;
    }

还有Elasticsearch运行,这当然也有影响。有谁知道如何改进吗?例如,是否有一种方法可以在存储库重新插入上禁用Elasticsearch的索引?是否有更好的方法来减少内存的使用?

谢谢你的建议!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-08 07:56:50

您是在devprod环境中运行这个程序吗?强烈建议您在prod环境中执行这样的大规模数据操作。

通过异步索引数据,可以大大加快进程的速度。这将填充消息队列。实体通常会以这种方式以更快的速度持久化,但在队列中的消息被处理之前,可能仍然缺少一些基本数据。通过设置上下文状态,可以设置为队列中的索引数据:

代码语言:javascript
复制
$context->addState(EntityIndexerRegistry::USE_INDEXING_QUEUE);

您也可以完全禁用索引,但不建议这样做:

代码语言:javascript
复制
$context->addState(EntityIndexerRegistry::DISABLE_INDEXING);

另一种选择是跳过特定的索引器。如果您确实知道不需要索引特定数据,则可以将其设置为跳过整个实体索引器或特定更新程序

代码语言:javascript
复制
$context->addExtension(EntityIndexerRegistry::EXTENSION_INDEXER_SKIP, new ArrayEntity(['category.indexer']));
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73274264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档